洛谷P2727 01串 Stringsobits

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 } 

猜你喜欢

转载自www.cnblogs.com/Msmw/p/11330640.html