题意:输入一个二进制数(1<<1000)和一个K,有这样一种变换,(1101)2->3==(11)2-->2==(10)1-->1,所以f(1101) = 3,问比这个二进制小的且f(bit) == k的数有几个
题解:这个二进制最多1000个1, 设dp[i][j]代表前i位小于这个二进制而且1的个数为j的个数,
那么bit[i] == 1:dp[i][j] = dp[i-1][j-1]+c[i-1][j];(c[i][j]为组合数)
bit[i] == 0:dp[i][j] = dp[i-1][j];
接下来就要找出走K次的数
假如一个数走一次,f(a) = b那么b<1000
所以枚举b,1到1000计算出所有走(k-1)次的数相加就是答案
注意这里要考虑k == 0和k == 1的情况...........
#include <bits/stdc++.h> #define maxn 101000 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; ll k, a[maxn], dp[1010][1010], l, mod = 1e9+7, ans1[1010], cnt, C[1010][1010]; char s[1010]; ll get(ll x) { ll sum = 0; while(x) { if(x&1) ++sum; x >>= 1; } return sum; } ll c(ll a,ll b){ if(a<b) return 0; else return C[a][b]; } int main(){ scanf("%s", s); l = strlen(s); cin>>k; C[1][0] = C[1][1] = 1; for (int i = 2; i < 1010; i++){ C[i][0] = 1; for (int j = 1; j < 1010; j++) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1])%mod; } for(ll i=l-1;i>=0;i--) a[l-i] = s[i]-'0'; if(a[1]) dp[1][1] = 1, dp[1][0] = 1; else dp[1][1] = 0, dp[1][0] = 1; for(ll i=2;i<=l;i++){ dp[i][0] = 1; for(ll j=1;j<=l;j++){ if(a[i]) dp[i][j] = (dp[i-1][j-1]+c(i-1, j))%mod; else dp[i][j] = dp[i-1][j]%mod; } } ll ans = 0; for(ll i=1;i<=1000;i++) { ll tmp = get(i); if(i==1) ans1[i] = 0; else ans1[i] = ans1[tmp]+1; if(ans1[i]==k-1) ans = (ans+dp[l][i]) % mod; } if(k == 0) ans = 1; if(k == 1) ans = dp[l][1]-1; cout<<ans<<endl; return 0; }