リンク:https
://ac.nowcoder.com/acm/problem/14731出典:Niuke
次の条件を満たす、長さnのすべての01文字列内の2つのタプルの数を見つけます
。i番目とj番目のビットをそれぞれaiとajに設定し(i <j)、次にai = 1、aj = 0 。
答えはモジュロ1e9 + 7です。
アイデア
データ範囲n <10 ^ 18、暴力は絶対にありそうもないので、式を考慮する必要があります
質問の意味によると、質問の意味を満たす文字列内の2つのタプルの数は、すべての0桁の前の1の数の合計、または各1桁の後の0の数の合計です。
最初のタイプについて話し
ましょう。すべての可能な01文字列の最初のi-1桁の場合、1の数は(i-1)/ 2 * 2 ^(i-1)です。i + 1〜nビット(2 ^(ni)が可能)の場合、i位置での0の寄与には影響しないため、
2 ^(ni)を掛け
ます。したがって、i位置が0であるすべての文字列に対して答えへのビットの寄与は(i-1)* 2 ^(n-2)
i 2〜n sum ans =(n-1)n 2(n-3)
コード
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod = 1e9 + 7;
ll fun(ll x,ll y){
ll f = x;
x = 0;
while(y){
if(y&1)
x = (x + f) %mod;
y >>=1;
f = (f + f)%mod;
}
return x;
}
ll qqow(ll x){
ll f = 2;
ll ans = 1;
while(x){
if(x&1)
ans = fun(ans,f)%mod;
x>>=1;
f = fun(f,f)%mod;
}
return ans;
}
int main(){
ll n;
cin >> n;
ll ans;
if(n <= 1){
cout << 0;
return 0;
}
if(n == 2){
cout << 1;
return 0;
}
ans=(n%mod)*((n-1)%mod)%mod*qqow(n-3)%mod;
//ans = fun(fun(n,n-1),qqow(n-3));
cout << ans << endl;
return 0;
}