1. 程式人生 > >Codeforces 914 C 數位DP+暴力打表+思維

Codeforces 914 C 數位DP+暴力打表+思維

return span 每次 amp bits sin fine inline cout

題意

給出一個二進制數\(n\),每次操作可以將一個整數\(x\)簡化為\(x\)的二進制表示中\(1\)的個數,如果一個數簡化為\(1\)所需的最小次數為\(k\),將這個數叫做特殊的數,

問從\(1\)\(n\)一共有多少個特殊的數,答案對\(1e9+7\)取模。

分析

\(n\)最大為\(2^{1000}\),二進制表示中最多有\(1000\)\(1\),所以\(n\)以內的數經過一次簡化後將變為\(1000\)以內的數,我們可以暴力打表\(1000\)以內的數簡化為\(1\)所需的最少次數,將求得的次數加\(1\)即為二進制中\(1\)的個數為\(x\)的數簡化為\(1\)所需的最少次數為\(cnt[x]\)

\(1\)這個數要特判,沒特判wa了3發。。。

然後分情況討論:

  • \(k=0\),答案為\(1\),只有\(1\)是經過\(0\)次簡化到\(1\)的數
  • \(k=1\),答案為\(n\)的位數\(-1\)\(n\)除了第\(1\)位,其余每一位為\(1\)都是特殊的數

  • \(k>1\),直接數位dp,設\(dp[i][j]\)為枚舉到第\(i\)位二進制中\(1\)的個數為\(j\)\(cnt[x]==k\)的數為特殊的數

Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    const double PI=acos(-1.0);
    const double eps=1e-6;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=1e5+10;
    char s[1010];
    int a[1010],cnt[1010],k;
    ll dp[1010][1010];
    ll dfs(int pos,int x,int limit){
        if(pos==0) return cnt[x]==k;
        if(!limit&&~dp[pos][x]) return dp[pos][x];
        int up=limit?a[pos]:1;
        ll ret=0;
        for(int i=0;i<=up;i++){
            ret+=dfs(pos-1,x+(i==1),limit&&i==a[pos]);
            ret%=mod;
        }
        if(!limit) dp[pos][x]=ret;
        return ret;
    }
    int solve(int x){
        if(x==1) return 0;
        int ret=0;
        int cnt=0;
        while(x){
            if(x&1) cnt++;
            x>>=1;
        }
        ret+=solve(cnt)+1;
        return ret;
    }
    void init(int n){
        for(int i=1;i<=n;i++){
            cnt[i]=solve(i)+1;
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        init(1005);
        memset(dp,-1,sizeof(dp));
        cin>>s+1>>k;
        int n=strlen(s+1);
        for(int i=1;i<=n;i++){
            a[n-i+1]=s[i]-'0';
        }
        if(k==1){
            cout<<n-1;
        }else if(k==0) cout<<1;
        else cout<<dfs(n,0,1);
        return 0;
    }

Codeforces 914 C 數位DP+暴力打表+思維