2019ICPC南昌站C.And and Pair


題意:

  給一個二進制數n,求滿足0<=j<=i<=n且i&&n==i&&i&j==0的數對(i,j)有多少對,n可能有前導0.

解析:

  對一一個特定的i(例如0101010)來說,設從低位到最高位的1之間有x個0,可選擇的j就是2x種(i為0的位置j可以選0/1,i為1的位置j為0),從低位向高位枚舉每個數字,當遇到1時,讓他做最高位的1,設這個1的低位中有y個1和x個0,簡單推導得到有2x*∑Cyi2i=2x*3y種方案。(∑Cni2i值得一提的是這個的物理意義就是枚舉每個子集的每個子集,是子集dp的時間復雜度)

代碼:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
const int mod=1e9+7;
const int maxn=1e5+10;
ll num2[maxn];
ll num3[maxn];
char a[maxn];

int main(){
    ll t;
    scanf("%lld",&t);
    getchar();
    num2[0]=num3[0]=1;
    for(int i=1;i<maxn;i++){
        num2[i]=(num2[i-1]*2)%mod;
        num3[i]=(num3[i-1]*3)%mod;
    }
    while(t--){
        scanf("%s",a);
        ll len=strlen(a);
        ll y,x;
        y=x=0;
        ll num=0;
        for(ll i=len-1;i>=0;i--){
            if(a[i]=='1'){
                num=(num+(num2[x]*num3[y])%mod)%mod;
                y++;
                //printf("%lld %lld %lld \n",num2[x],num3[y],num);
            }
            else x++;
        }
        num=(num+1)%mod;//只算了i的最高位位1的情況,要算上i==0的情況
        printf("%lld\n",num);
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM