USACO Training3.2 01串 By cellur925

题目传送门

一句话题意:求长度为n的有m个1的大小为第k个的01串。

 

暑假我做的时候是真·大暴力,用二进制枚举,55分,成功T掉无数点。

 

正解:开始可以用计数类dp来“预处理”,状态和转移都比较好想。

  状态:设f[i][j]表示i位二进制数,1的个数不超过j的种类数。

  转移:f[i][j]=f[i-1][j]+f[i-1][j-1] (当前位取0或1)

  初值:f[i][0]=0,f[0][i]=0;

然后?我们尝试倒序枚举答案。我们知道在二进制中最高位为1时一定比最高位为0的情况大,所以我们在尝试的过程中,如果当前的k仍大于f[i-1][j],则第i位一定为1,因为还没达到第k个的要求。所以我们不断将k减去f[i-1][j],这样不断向下枚举就能得到答案。

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 
 4 using namespace std;
 5 typedef long long ll;
 6 
 7 int n,m;
 8 ll pos,f[100][100];
 9 
10 int main()
11 {
12     scanf("%d%d%lld",&n,&m,&pos);
13     for(int i=0;i<=n;i++) f[i][0]=1,f[0][i]=1;
14     for(int i=1;i<=n;i++)    
15         for(int j=1;j<=m;j++)
16             if(j<=i) f[i][j]=f[i-1][j]+f[i-1][j-1];
17             else f[i][j]=f[i][i];
18     int a=n,b=m;
19     while(a!=0)
20     {
21         if(pos>f[a-1][b])
22         {
23             pos-=f[a-1][b];
24             printf("1");
25             a--;b--;
26         }
27         else
28         {
29             printf("0");
30             a--;
31         }
32     }
33     printf("\n");
34     return 0;
35 }
View Code

* 注意:开long long 。防止越界。(2^31)

posted @ 2018-09-11 21:34  cellur925&Chemist  阅读(129)  评论(0编辑  收藏  举报