【每日一题】4月16日 组合数学
逆序对
https://ac.nowcoder.com/acm/problem/14731
include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 2e5+5;
const int M = 1e6;
const int Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e8
#define INM INT_MIN
#define pb(a) push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define met0(axx) memset(axx,0,sizeof(axx));
#define metf(axx) memset(axx,-1,sizeof(axx));
#define sd(ax) scanf("%d",&ax)
#define sld(ax) scanf("%lld",&ax)
#define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
#define sdd(ax,bx) scanf("%d %d",&ax,&bx)
#define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
#define sfd(ax) scanf("%lf",&ax)
#define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
考虑任意两个位置作为1,0,构成的串的个数.
很明显当两个位置i = 1,j = 0时。
其他位置都有2种选择。那么构成的不同串数就是2222..... = 2^(n-2).
所以每一对位置都可以构成这么多串,然后把每对位置看成独立地去计算就可以了.
对于每对位置,那么就任选一对位置C(n,2).(n(n-1)/2)
注意特判n = 1,因为就会 n-2 = -1.
所以总次数就是C(n,2)2^(n-1).
一些思考:
为什么可以将这些位置单独拿出来看呢.
因为我们其实是列举出了所有的位置情况,然后将这些位置情况里的固定一对位子的贡献求解出来。
所以事实上我们枚举的这些情况中很多都是重复的,但是对于我们固定的枚举的位置,这些形成的最后串是不一样的.
又因为他们有共性,所以我们可以得到这个结果.
LL quick_mi(LL a,LL b) { LL re = 1; while(b) { if(b&1) re = (re*a)%Mod; b >>= 1; a = (a*a)%Mod; } return re%Mod; } int main() { LL n;sld(n); LL t = (n%Mod*((n-1)%Mod)/2)%Mod;//注意这里的取模,应该先n%mod,和(n-1)%mod之后在乘.如果只n%mod*(n-1)%mod的话.n%mod*(n-1)也会爆longlong. if(n == 1) printf("0\n"); else plr(t*quick_mi(2,n-2)%Mod); system("pause"); return 0; }