Wannafly挑战赛25 C期望操作数 (dp+逆元)

题意:链接:https://www.nowcoder.com/acm/contest/197/C
来源:牛客网

Nqijij 有一个数x,和一个神秘权值 q, 满足 x <= q, 每一次nqijij会随机x 变成 [x, q] 中的一个随机数,nqijij想要知道期望多少次操作之后x 变为q。
由于nqijij 是一个精力充沛的人,所以他总共会选择 T 次x 和q 进行操作,对于每一次操作,你需要输出期望多少次操作之后x 变为q 在 998244353 模意义下的值。

(令 ans = x / y, x, y 为正整数且 题目保证 x、y 与998244353 互质,则输出x * (y^(-1)), (y^(-1)) 表示y在998244353下的乘法逆元,可以证明这样的逆元存在)

题目保证 T <= 1e6, q <= 1e7, x <= 1e7;

思路:举例x=11,q=14,dp[i]表示i到q的期望操作数。那么dp[11]=dp[11]/4+dp[12]/4+dp[13]/4+dp[14]/4+1含义是11有四种可能变化,所以概率是1/4,然后这一步操作增加了期望的操作,所以+1,以此类推,让dp[i]表示区间长度为i的期望操作数,所以dp[3]=dp[1]/4+dp[2]/4+dp[3]/4+dp[0]/4+1,移项,得到(1-1/4)dp[3]=(dp[0]+dp[1]+dp[2])/4+1,递推公式就是Wannafly挑战赛25 C期望操作数 (dp+逆元)_第1张图片

至于为什么要写成下面那样,主要是为了好求逆元,这样就只用求i的逆元,最后线性预处理一下逆元就行了。

#include
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=1e7+10;
const int mod=998244353;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qpow(ll a,ll b){ll t=1;while(b){if(b%2){t=(t*a)%mod;b--;}a=(a*a)%mod;b/=2;}return t;}
//ll inv(ll a,ll p){return qpow(a,p-2);}
ll dp[maxn],inv[maxn];

void get_inv()                  //递推求1~n的逆元
{
    inv[1] = 1;
    for(int i=2; i

 

你可能感兴趣的:(数论,动态规划)