1. 程式人生 > >拆數遊戲dp

拆數遊戲dp

歡迎訪問鄭州大學程式設計線上評測系統(ZZUOJ)!  ZZUACM招新群號:562888278


問題4317--有趣的拆數遊戲

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 <bits/stdc++.h>
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;
}