1014 小A买彩票 认真地题解 线性DP 动态规划
链接:https://ac.nowcoder.com/acm/contest/24213/1014
来源:牛客网
题目描述
输入描述:
一行一个整数N,为小A购买的彩票数量一行一个整数N,为小A购买的彩票数量一行一个整数N,为小A购买的彩票数量
输出描述:
备注:
0≤n≤300 \leq n \leq 300≤n≤30
分析
n = 0 的时候,肯定不会亏输出 1/1
有4个选项,n次选择。所以总共有 4 ^ n 的结果作为分母。
4 ^ 30 = 2 ^ 60 所以要开LL
n >=1 的时候,首先看n = 1 ,有2/4的概率是亏的。
随着n 的增大,最后一次的方案数总是和最后一次有关,所以第i次选择是线性DP 的一个变量
每次选择的区别还在于最后得到的金钱数,所以有j 块钱是线性DP 的一个变量
得到变量:dp[i][j] 表示第i次选择总共得到了j块钱
第i 次和第i - 1 次在金钱方面的区别就是 j -1 ,j - 2 ,j - 3 ,j - 4
所以第i 次得到j块钱的方案数 按照搜索的分部加法原理就是 dp[i][j] = dp[i-1][j-1] + dp[i-1][j-2] + dp[i-1][j-3] + dp[i-1][j-4]
初始化dp[1][1] = dp[1][2] = dp[1][3] = dp[1][4] = 1
i 从 2 开始循环
j 从 当前轮最小金额数 i 开始循环到 4 * i
最后用最大公约数除分子和分母,得到通分
写了这么久题解,终于开始认真写了
//-------------------------代码----------------------------
#define int LL
const int N = 2000;
int n,m;
int dp[N][N];
void solve()
{
cin>>n;
if(n == 0) {
cout<<"1/1";
rt;
}
for(int j=1;j<=4;j++)
dp[1][j]=1;
fo(i,2,n) {
fo(j,i,i*4) {
dp[i][j] = dp[i-1][j-1] + dp[i-1][j-2] + (j-3 >= 0 ?dp[i-1][j-3]:0) +
(j-4>=0?dp[i-1][j-4]:0);
}
}
LL sum = 0;
fo(i,3*n,4*n) {
sum += dp[n][i];
}
LL f = pow(4,n);
int z = gcd(f,sum);
cout<< sum / z <<'/'<< f / z;
rt;
}
signed main(){
clapping();TLE;
// int t;cin>>t;while(t -- )
solve();
// {solve(); }
return 0;
}
/*样例区
*/
//------------------------------------------------------------