解题思路:

  题目的例子为例,长度为7位的01字串按3位一段就这样分:0 000 000。其中除了首段,每段都小于(111)2,也即小于2k,而首段自然是小于2w%k(对于w%k为0时也成立)了。

    如果首段为0,则当这个2k进制数位数分别为2、3、…、[n/k]时,如果用b_max表示2k,对应的解的个数分别为C[b_max-1][2]、C[b_max-1][3]、…、C[b_max-1][n/k](C[i][j]表示从i个数里选j个构成一组组合)。

    如果首段不为0,设首段为x,则解就有c[b_max-x-1][n/k]个。

    这样,求解的个数就搞定了,剩下的活就是高精了。求组合数可以用这个公式:C[n][m]=C[n-1][m-1]+C[n-1][m],这样高精就只用加法了。


注意事项:





参考代码:

#include<cstdio>  

#include<algorithm>  

#include<iostream>

#define maxn1 200  

#define maxn2 1000  

using namespace std;


int ans[maxn1 + 20];

int f[maxn2 + 100][maxn1 + 20];


void add(int a[], int b[])

{

int i, j, k, last = 0;

a[0] = max(a[0], b[0]);

for (i = 1; i <= a[0]; i++)

{

a[i] += b[i] + last;

last = a[i] / 10, a[i] %= 10;

}

if (last>0)a[++a[0]] = last;

}


int main()

{

int i, j, k, x, y, w;

cin >> k >> w;

if (w <= k) { 

cout << "0" << endl; 

return 0;

}


y = (1 << k) - 1;

if (w%k == 0)x = y, k = w / k - 1;

else x = (1 << (w%k)) - 1, k = w / k;


f[1][0] = 1, f[1][1] = 1;

ans[0] = 0;


for (i = 1; i <= y; i++)

{

for (j = i + 1; j >= 1; j--)

add(f[j], f[j - 1]);

if (i >= y - x && i<y)add(ans, f[k + 1]);

}

for (i = 3; i <= k + 1; i++)

add(ans, f[i]);

for (i = ans[0]; i >= 1; i--)

cout << ans[i];

cout << endl;

return 0;

}


点赞(3)
 

0.0分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论