题意:给出一个长度为n的“01”串,问:统计所有01串的逆序对总数
分析: 首先对于逆序对,满足 设第i位和第j位分别位ai和aj(i<j),则ai=1,aj=0。
只有当出现 1 0 这种样子串,才会对结果造成影响,所以先从n个中选出2个。
剩下n-2个数就有2^(n-2)种情况,也就是这几种情况会有贡献。
所以ans=C(n,2)*2^(n-2)
细节的话就是取mod,不要漏取mod,很容易炸
下面给出2中写法,一种是常规求组合数,用逆元+费小马定理。因为题目比较特殊,上面的ans可以化简成ans=(n-1)n2^(n-3) 所以第二种没必要用逆元
第一种:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <cctype>
#include <cmath>
#include <cassert>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll n;
int main()
{
while(~scanf("%lld",&n))
{
if(n==1)
{
printf("0\n");
continue;
}
if(n==2)
{
printf("1\n");
continue;
}
//C(n,2)*2^(n-2)
// a/b%mod== a*(b的逆元)%mod
// b的逆元%mod=pow(b,mod-2)
ll a=((n%mod)*((n-1+mod)%mod))%mod;
ll c=((a%mod)*(powmod(2ll,mod-2ll)%mod))%mod;
ll ans=((c%mod)*(powmod(2ll,n-2ll)%mod))%mod;
printf("%lld\n",ans%mod);
}
return 0;
}第二种
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <deque>
#include <set>
#include <stack>
#include <cctype>
#include <cmath>
#include <cassert>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll n;
int main()
{
while(~scanf("%lld",&n))
{
if(n==1)
{
printf("0\n");
continue;
}
if(n==2)
{
printf("1\n");
continue;
}
ll ans=((((n%mod)*((n-1+mod)%mod))%mod)*powmod(2ll,n-3)%mod)%mod;
printf("%lld\n",ans%mod);
}
return 0;
}
京公网安备 11010502036488号