标签:mamicode gcc png mat des span 期望 code zoj
首先看一下\(p=1\),即\(1\)以后的合成一定成功的情况
如果按照求期望值的一般做法求两把\(0\)合成\(1\)的期望,会画出一棵无穷大的树
这个的期望值就是\[a+\sum^{∞}_{i=1}ap(1-p)^{i-1}\]
通过数列知识或者打表找规律可以知道这个值为\(a+{a\over p}\)(或者说是\(f[0]+{f[0]\over p}\))
设\(f[i]\)为合成一把\(i\)级剑的期望,\(f[1]\)单独计算,后面的\(f[i]=f[i-1]+f[i-2]\)
扩展到\(100pts\)的情况,如果\(i\)级剑合成失败了,会产生一把\(i-2\)级的剑
也就是说下一次合成\(i\)级剑,只需要合成\(i-1\)级剑,不需要再搞来一把\(i-2\)级剑
同理再画一棵期望树,每次成功的代价是\(f[i-1]\),一开始就有的代价是\(f[i-2]\)
\[f[i-2]+\sum_{i=1}^∞f[i-1]p(1-p)^{i-1}\]
根据已知的规律,所以\(f[i]={f[i-1]\over p}+f[i-2]\)
下次要好好动脑,\(60pts\)都想出来了,要想再深入一点,争取拿分
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 10000005
#define mod 998244353
#define ll long long
#define reg register int
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
using namespace std;
int inv[MAXN],b[MAXN],c[MAXN],f[MAXN];
int n,a,bx,by,cx,cy,p;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
int main()
{
freopen("T1.in","r",stdin);
//freopen("forging.in","r",stdin);
//freopen("forging.out","w",stdout);
n=read(),a=read(),bx=read(),by=read(),cx=read(),cy=read(),p=read();
inv[1]=1;fo(i,2,p)inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
b[0]=by+1,c[0]=cy+1,f[0]=a;
fo(i,1,n)
{
b[i]=((ll)b[i-1]*bx+by)%p+1;
c[i]=((ll)c[i-1]*cx+cy)%p+1;
ll tmp=(1ll*c[i-1]*inv[min(c[i-1],b[max(i-2,0)])])%mod;
f[i]=(1ll*(f[max(i-2,0)]+1ll*f[i-1]*tmp%mod))%mod;
}
printf("%d\n",f[n]);
return 0;
}
标签:mamicode gcc png mat des span 期望 code zoj
原文地址:https://www.cnblogs.com/horizonwd/p/11302278.html