鍛造 (forging)
題目描述
Input
第一行兩個整數 n, a,含義如題所示。
爲了避免輸入量過大,第二行五個整數 bx, by, cx, cy, p,按照下列代碼
來生成 b 和 c 數組。
b[0]=by+1;c[0]=cy+1;
for(int i=1;i<n;i++){
b[i]=((long long)b[i-1]*bx+by)%p+1;
c[i]=((long long)c[i-1]*cx+cy)%p+1;
}
Output
輸出一行一個整數,表示期望花費。
Sample Input
Sample Input1
0 6432
4602677 3944535 2618884 6368297 9477531
Sample Input2
1 3639650
6136976 5520115 2835750 9072363 9302097
Sample Input3
10 2
2 33 6 66 2333333
Sample Input4
200 5708788
0 0 0 0 1
Sample Output
Sample Output1
6432
Sample Output2
150643649
Sample Output3
976750710
Sample Output4
696441597
Data Constraint
題解
不知道爲什麼,看到概率就會想到…
當然這道題顯然是一道。
因爲在考場上我對這道題極其有研究,所以講得稍微詳細一點。
雖然這道題很簡單,但是我們從頭開始(但是我太菜了)。
首先看到,直接就是嘛沒什麼可說的。
然後想了一下暫時還有點懵逼(開始讀題讀錯了)。
於是考慮。
我們先定義一下(方便表示):表示得到一把級劍的期望花費
顯然
這裏我們想到這個操作可以失敗的次數是不確定的,既是我們假設我們經過次失敗後成功,既是需要把級劍,然後這種情況對最後答案的貢獻是:
可以得到
令,即
所以我們就是要求
令
因爲,所以
則
將代入
則
所以
於是就處理完了,我們再看看還有什麼是容易做的。
看到有再一想,就是除了合成1級劍,其它都是一定成功。
就很容易了。
其中知道。
所以我們已經有60分了,NICE
開始考慮正解。
發現每一次合成一把級劍,都是要用把級劍和1把級劍。
類比考慮合成1級劍的過程,我們得到
大家自己對照前面的過程化簡一下會得到
這本身也是可以理解的。
再加一個逆元就好了。
要線性篩逆元不然會T。
(線性篩逆元)
代碼
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=int(1e7+5);
typedef long long LL;
#define mod 998244353
LL n,a;
LL b[MAXN];
LL c[MAXN];
LL dp[MAXN];
LL XINV[MAXN+5];
LL Pow(LL a,LL b) {
long long ret=1,x=(long long)a,y=(long long)b;
while(y) {
if(y%2)
ret=ret*x%mod;
y/=2;
x=(x*x)%mod;
}
return LL(ret)%mod;
}
LL Inv(LL a) {
return Pow(a,mod-2);
}
void Prepare() {
XINV[1]=1;
for(int i=2;i<=MAXN;i++)
XINV[i]=XINV[mod%i]*(mod-mod/i)%mod;
}
int main()
{
Prepare();
freopen("forging.in","r",stdin);
freopen("forging.out","w",stdout);
LL bx,by,cx,cy,p;
scanf("%lld%lld",&n,&a);
scanf("%lld%lld%lld%lld%lld",&bx,&by,&cx,&cy,&p);
b[0]=by+1,c[0]=cy+1;
for(LL i=1;i<n;i++) {
b[i]=(long long)(b[i-1]*bx+by)%p+1;
c[i]=(long long)(c[i-1]*cx+cy)%p+1;
}
if(n==0) {
printf("%lld",a);
return 0;
}
else if(p==1||n==1) {
LL inv=XINV[c[0]],Min=min(c[0],b[0]);
LL P=(LL)inv*Min%mod;
LL ans=(LL)a*(1+P)%mod*Inv(P)%mod;
dp[0]=a,dp[1]=ans;
for(LL i=2;i<=n;i++)
dp[i]=(dp[i-1]+dp[i-2])%mod;
printf("%lld",dp[n]);
}
else {
LL inv=XINV[c[0]],Min=min(c[0],b[0]);
LL P=(LL)inv*Min%mod;
LL ans=(LL)a*(1+P)%mod*Inv(P)%mod;
dp[0]=a,dp[1]=ans;
for(LL i=2;i<=n;i++) {
LL MIN=min(c[i-1],b[i-2]);
LL INV=XINV[MIN];
dp[i]=((LL)dp[i-1]*c[i-1]%mod*INV%mod+dp[i-2])%mod;
}
printf("%lld",dp[n]);
}
}
如果MLE就把一些LL改爲int