欢迎访问郑州大学程序设计在线评测系统(ZZUOJ)! ZZUACM招新群号:562888278
问题4317--有趣的拆数游戏
时间限制: 1 Sec 内存限制: 128 MB
提交: 28 解决: 8
[提交] [状态] [讨论版] [命题人:admin]
题目描述
Zxy 特别喜欢数学,他看到过许多有趣的拆数题,比如:把一个数拆成两个质数的和或者将一个数拆成若干个数的和,使得它们的乘积最大,当然这些都是简单的的问题了,对于热爱算法竞赛并且足够优秀的你,当然不用解决这些简单的问题啦。
现在zxy需要有一个拆数问题交给你。
对于一个整数n,你可以将它拆成若干个数的和,例如
1: {1}
2: {1+1, 2}
3: {1+1+1, 1+2, 2+1, 3}
4: {1+1+1+1, 1+1+2, 1+2+1, 1+3, 2+1+1, 2+2, 3+1, 4}
注意:同样的集合元素顺序不同,我们也认为它们是不同的!
zxy想要统计到底有多少种拆分整数n的方法,所以一个个写下所有的可能,zxy的队友孙刚来趁zxy不注意就把一些方案擦去了,zxy很生气但是又没有办法。他发现擦去的集合都有一些特点,就是这个集合的元素里面含有偶数。
例如对于1,2,3,4剩下的拆分方法是:
1: {1}
2: {1+1}
3: {1+1+1, 3}
4: {1+1+1+1, 1+3, 3+1}
zxy突然灵机一闪,想知道对于一个整数n,不含有{m+i*k∣i=0,1,...}集合内元素的拆分方法共有多少个?
输入
第一行一个整数T(T<= 60),代表测试样例的数量
一个样例包括一行包含三个整数 n,m,k( 1<=n<=30,0<=m,k<30)
输出
T行,每行输出当前组数据拆分方法的数量
样例输入
3
10 0 2
15 1 4
28 3 7
样例输出
55
235
18848806
#include
using namespace std;
const int maxn=31;
int dp[maxn];
int n,m,k,T;
bool check(int x)
{
if((x-m)%k) return true;
else return false;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&k);
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
if(check(j)) dp[i]+=dp[i-j];
}
}
printf("%d\n",dp[n]);
}
return 0;
}