题目大意:中文题,略。
题目分析:
其实就是求给k个数,每个数可以是1,2,或者3,求这k个数的和大于t 的方案数。
dp[i][j]表示用j个数的和为i的方案数。那么很容易得到转移方程:
dp[i][j] = dp[i - 1][j - 1] + dp[i - 2][j - 1] + dp[i - 3][j - 1]。
即用j个数和为i的方案数为:(用j-1个数和为i-1的方案数,第j个数为1)+(用j-1个数和为i-2的方案数,第j个数为2)+( 用j-1个数和为i-3的方案数,第j个数为3)。
然后就是直接统计输出了。要求的是sigma(dp[i][k]),其中i>t。
第二维可以省掉的样子。
比较基础的dp。。好久没有正儿八经的写dp了。
明显的dp竟然用搜索做,真是作死。。。
征服DP!!
详情请见代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
const int N = 30005;
typedef __int64 ll;
int a,b,last,score;
ll dp[N][55];
ll ans;
ll dpp[N];
int main()
{
int i,j,t;
memset(dp,0,sizeof(dp));
memset(dpp,0,sizeof(dpp));
dpp[1] = 1;
for(i = 3;i < N;i ++)
dpp[i]
dp[1][1] = dp[2][1] = dp[3][1] = 1;
dp[2][2] = 1;
for(i = 3;i < N;i ++)
{
for(j = 2;j <= 50;j ++)
dp[i][j] = dp[i - 1][j - 1] + dp[i - 2][j - 1] + dp[i - 3][j - 1];
}
while(scanf("%d%d%d",&a,&b,&t) != EOF)
{
last = t / 15;
b += (last /2 );
last -= (last /2 );
score = b - a;
if(score < 0)
{
printf("%I64d\n",(ll)pow(3.0,(double)last));
continue;
}
ans = 0;
for(i = score + 1;i <= last * 3;i ++)
ans += dpp[i];// dp[i][last];
printf("%I64d\n",ans);
}
return 0;
}