专栏文章
题解:P11998 哇,这就是 5p
P11998题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mippv8k7
- 此快照首次捕获于
- 2025/12/03 15:59 3 个月前
- 此快照最后确认于
- 2025/12/03 15:59 3 个月前
首先我们可以发现时限两秒,也就是说明 可以通过去,这就为我们实现动态规划这个算法奠定了基础 当然应该有比这个时间复杂度更快的做法。
我们不妨设计一个状态 ,用来表示做到第 道题时,此时的分数除以 的余数为 的概率为多少。
那此时此刻对于第 道题有两种选择:
-
假如这题做对了,那 需要加上 。
-
假如这题没做对,那 需要加上 。
所以动态转移方程就是 , 为 。
注: 用来表示 的结果,就是没做对的概率。以下为推理过程:
- 题目已经说了 一定能够被表示成 的形式,且 ,再根据题目说的有理数取余,则 。现令 为 ,则 可表示为 ,所以 的结果为 ,根据 费马小定理, 在模 的情况下就为 ,而 在模 的情况下就为 ,在代入回去就可以得到了。
但是这样子数组的空间可能会爆掉,但我们可以发现一个状态的转移只会依赖上一个状态的结果,所以我们就可以用滚动数组来优化。
代码部分:
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+1,mod=998244853;
int n,m,a[N],p[N],tot,dp[2][1001];
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]%=m;
for(int i=1;i<=n;i++) scanf("%lld",&p[i]);
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
int tott=tot^1;
memset(dp[tott],0,sizeof(dp[tott]));
for(int j=0;j<m;j++)
{
dp[tott][j]+=dp[tot][j]*((1-p[i]+mod)%mod)%mod,dp[tott][j]%=mod;
dp[tott][j]+=dp[tot][(j-a[i]+m)%m]*p[i]%mod,dp[tott][j]%=mod;
}
tot=tott;
}
printf("%lld",dp[tot][0]);
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...