C - And and Pair
C - And and Pair
題意:
問有多少組(i,j)滿足要求。
要求為:
0<=j<=i<=n
i&n=i
i&j=0
答案mod 1e9+7
題解:
這個和我的思路時一樣的,且講的更清楚
i&n=i說明n為0的地方,i必須為0;n為1的地方,i隨意(兩種選擇)
i&j=0說明i為1的地方,j必須為0;i為0的地方,j隨意(兩種選擇)
j還要<=i
所以我的思路:
對于一組S:101010
我們從前往后開始掃,第一位為1時,我們可以認為i在這一位是1,對于j的取值,因為j在i為0的地方隨便取,后面5位中,最少有3個0,最多有5個0(因為1的位置i是隨便取得,i可以選1)
那么對于i為10x0x0(x表示這位有兩種情況),我們可以確定j的情況,j為0x?x?x,(x表示有兩種選擇,?表示要根據i的情況定)
這個情況的答案就是:
0的個數為3個:C20 *23
0的個數為4個:C21 *24
0的個數為5個:C22 *25
求和:
sum=C20 *23+C21 *24+C22 *25
我們把23提出來:
sum=23 (C20 *20+C21 *21+C22 *22)=23 (2+1)2
(用的二項式定理,比賽時沒想到:)
(x+1)n= (Cn0 *x0+Cn1 *x1+…+Cnn *xn)
現在將結論推廣:
設k為后面0的數量
t為后面1的數量
答案就是sum=2k 3t
遍歷字符串,不斷更新k和t,然后取和
代碼:
#include <bits/stdc++.h> #define ll long long #define maxn 100001 using namespace std; const ll mod = 1000000007;ll pow_2[maxn+10],pow_3[maxn+10];ll power(ll a,ll b){ll res = 1;while(b){if(b&1) res = res*a%mod;a = a*a%mod;b>>=1;}return res; }void init(){for(int i=0;i<=maxn;i++){pow_2[i] = power(2,i);pow_3[i] = power(3,i);} }int main(){init();int t;string s; cin>>t;while(t--){ll num0=0,num1=0,sum=0;cin>>s;for(int i=0;i<s.size();i++){if(s[i]=='0') num0++;//0的數量 else num1++;//1的數量 }for(int i=0;i<s.size();i++){if(s[i]=='0'){num0--;//除了最高位0的數量 continue;}else{num1--;//除了最高位1的數量 sum = (sum + pow_2[num0] * pow_3[num1] % mod) % mod;}}cout<<(sum+1) % mod<<endl;}return 0; }總結
以上是生活随笔為你收集整理的C - And and Pair的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: L - Who is the Champ
- 下一篇: G - Eating Plan