P2727 01串 Stringsobits
看了题解才做(抄)出来的,dp好弱啊
dp[i][j]表示前i位有j个1的串数。
转移方程 dp[i][j]=dp[i-1][j-1]+dp[i-1][j]。
重点数如何求出这个串呢
我们对于k(0->l)遍历求前缀和。当发现对于对于前缀和 sum[i]>=p&&sum[i-1] 的,那么就一定有第i位是1,(应该很容易想到吧)
比较难的是接下来求下一位,因为当前这个是1,所以当前位为0的都一定被统计。我们只需要考虑当前位为1时,后面的的n-1位、l-1个1能带来p-sum[i-1]个串。
递归统计就可以了。注意边界,k要从0开始。
ps:感觉讲的十分不清晰 : (
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=32+5; 5 int n,m; 6 ll a[maxn]; 7 ll s[maxn]; 8 ll dp[maxn][maxn]; 9 int num[32]; 10 11 void solve(ll n,ll l,ll m) 12 { 13 ll s=0,last; 14 for(int i=0;i<=n;i++) 15 { 16 last=s; 17 s=0; 18 for(int j=0;j<=l;j++) 19 { 20 s+=dp[i][j]; 21 if(s>=m) 22 { 23 num[i]=1; 24 solve(n-1,l-1,m-last); 25 return; 26 } 27 } 28 } 29 } 30 int main() 31 { 32 std::ios::sync_with_stdio(false); 33 ll n,l,m;cin>>n>>l>>m; 34 //前i位1的个数位j的种类数 35 //dp[1][0]=1; 36 //dp[1][1]=2; 37 for(int i=0;i<=n;i++) dp[i][0]=1; 38 for(int i=1;i<=n;i++) 39 { 40 for(int j=1;j<=i;j++) 41 { 42 dp[i][j]=dp[i-1][j]+dp[i-1][j-1]; 43 } 44 } 45 //cout <<dp[1][1]<<endl; 46 47 solve(n,l,m); 48 for(int i=n;i>=1;i--) 49 if(num[i]) cout <<1; 50 else cout <<0; 51 cout <<endl; 52 return 0; 53 }