Niubiの1日1つの質問を逆の順序で

リンク: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;
}

おすすめ

転載: blog.csdn.net/RunningBeef/article/details/113921009