Solution
n >= 1e18, 显然是一道公式题
说实话, 这类题我一般是猜公式
先说说我怎么猜的
已知:
n = 1, ans = 0;
n = 2, ans = 1;
n = 3, ans = 6;
由于已知的组数太少, 我们考虑手玩出n = 4的情况
n = 4, ans = 24;
其次的话, 因为是01串, 一共有种摆放情况
我们考虑从的方向猜
可以看出
正经题解:
有n个地方可以放数字, 我们考虑在n个位置中取两个位置i, j(i < j) 令 a[i] = 1, a[j] = 0, 形成全部逆序对,
然后其他位置任意放置, 计算每个逆序对在每个字符串中的贡献
于是得到总的方案是, 证明上面的猜想是正确的
对了, 记得用快速乘!
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
const ll mod = 1e9 + 7;
const int DEG = 20;
const double PI = acos(-1.0);
const double eps = 1e-10;
const ll inf = 1e18;
const int N = 1e6 + 5;
static auto faster_iostream = []() {
std::ios::sync_with_stdio(false); // turn off sync
std::cin.tie(nullptr); // untie in/out streams
return 0;
}();
inline ll ksc(ll x, ll y, ll p){
ll z = (long double)x / p * y;
ll res = (unsigned long long)x * y - (unsigned long long)z * p;
return (res + p) % p;
}
ll qpow(ll a, ll b){
ll res = 1;
while(b){
if(b & 1){
res = ksc(res, a, mod);
}
a = ksc(a, a, mod);
b >>= 1;
}
return res;
}
int main(){
ll n;
cin >> n;
if(n == 1) cout << 0 << "\n";
else if(n == 2) cout << 1 << "\n";
else
cout << ksc(ksc(qpow(2, n - 3), n, mod), n - 1, mod) << "\n";
return 0;
} 
京公网安备 11010502036488号