记录编号 293132 评测结果 AAAAAAAAAAAAAAA
题目名称 [POI 1997] n-k集合数 最终得分 100
用户昵称 Gravatar浮生随想 是否通过 通过
代码语言 C++ 运行时间 0.119 s
提交时间 2016-08-09 19:02:27 内存使用 2.60 MiB
显示代码纯文本
  1. /*高精度+动归,f[i][j]表示前i个数中,大于等于j的集合有多少个。
  2. 则目标值为f[n][k+1],意义是在总共n个数中,大于等于k+1的集合有多少个。
  3. 则每一个f[i][j]有两个转移状态,第一个,i在集合中,则i-1不能在集合中,
  4. 所以转移应为f[i-2][max(0,j-i)],第二个,i不在集合中,则i-1
  5. 可以再集合中,所以转移应为f[i-1][j];
  6. 由于i在不在集合中,都属于f[i][j]可能情况,
  7. 故f[i][j]=f[i-1][j]+f[i-2][max(j-i,0)];
  8. */
  9. #include<cstdlib>
  10. #include<cstdio>
  11. #include<iostream>
  12. #include<cstring>
  13. #include<queue>
  14. #define ll long long
  15. using namespace std;
  16. const int maxn=110;
  17. void bigsum(int a[],int b[],int c[])
  18. {
  19. int len=max(a[0],b[0]);
  20. for(int i=1;i<=len;++i)
  21. {
  22. c[i]+=a[i]+b[i];
  23. c[i+1]=c[i]/10;
  24. c[i]%=10;
  25. }
  26. if(c[len+1]) len++;
  27. c[0]=len;
  28. }
  29. int f[maxn][410][55];
  30. int n,k;
  31. ll ans=0,cnt=0;
  32. int ma(){
  33. //freopen("余.txt","r",stdin);
  34. freopen("lic.in","r",stdin);
  35. freopen("lic.out","w",stdout);
  36. memset(f,0,sizeof f);
  37. scanf("%d%d",&n,&k);
  38. f[1][0][0]=1;f[1][1][0]=1;f[2][0][0]=1;
  39. f[2][1][0]=1;f[2][2][0]=1;
  40. f[1][0][1]=2;f[1][1][1]=1;f[2][0][1]=3;
  41. f[2][1][1]=2;f[2][2][1]=1;
  42. for(int i=3;i<=n;i++)
  43. for(int j=0;j<=k+1;j++)
  44. bigsum(f[i-1][j],f[i-2][max(j-i,0)],f[i][j]);
  45. bool flag=0;
  46. for(int i=f[n][k+1][0];i>=1;i--){
  47. if(f[n][k+1][i]==0&&!flag)continue;
  48. flag=1;
  49. printf("%d",f[n][k+1][i]);
  50. }
  51. if(!flag)printf("0");
  52. printf("\n");
  53. fclose(stdin);
  54. fclose(stdout);
  55. return 0;
  56. }
  57. int maaaa=ma();
  58. int main(){;}