6271. 2019.8.4【NOIP提高组A】锻造 (forging)
(File IO): input:forging.in output:forging.out
Time Limits: 1500 ms Memory Limits: 262144 KB Detailed Limits
Description
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
题目大意:
一个值为(i-1)和一个值为(i-2)的物品有p的几率合成一个(i)级物品 ,(1-p)的几率合成一个(i-2)级物品。拥有一把(0)等级的物品花费a。问得到一个n级物品的期望花费。
题解:
一道概率题。
f[i]表示合成一把i级武器的期望花费 。
我们合成失败后 , 得了一把(i-2)的剑 , 不用再锻造 , 只用在输了之后锻造一把(i-1)的剑即可 , 锻造的次数取决于合成成功的期望合成次数k。(若一次就合成成功了 , k=1 , f[i] = f[i-1] +f[i-2] ,退化成percent50(p=1)的形式)
f[i] = f[i-1] * k +f[i-2]
我们可以计算k。
期望次数 = P为赢的概率。(假设P为1% , 那我们就期望100次能出个i级剑)
k = (1\p)
f[i] = f[i-1] * (1/p) + f[i-2]
#include<bits/stdc++.h>
#define ll long long
#define re register
#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize(1)
#define mod 998244353
#define N 10000010
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
int n,a,i,j,r,ans,bx,by,cx,cy,p;
int f[N],inv[N];
int b[N] , c[N];
int main()
{
open("forging");
scanf("%d%d",&n,&a);
scanf("%d%d%d%d%d",&bx,&by,&cx,&cy,&p);
b[0]=by+1;c[0]=cy+1;
for(int i=1;i<n;i++){
b[i]=(((ll)b[i-1]*bx+by)%p+1);
c[i]=(((ll)c[i-1]*cx+cy)%p+1);
}
inv[1] = 1;
for(re int i=2;i<=p+1;i++)
(inv[i] = (-((ll)mod/i) * inv[mod % i])%mod + mod)%= mod;
f[0] = (ll)a % mod;
(f[1] = (ll)f[0] * inv[min(c[0],b[0])] % mod* (ll)c[0] %mod + f[0] )%= mod;
for(re int i=2;i<=n;i++)
(f[i] = (ll)f[i-1] * inv[min(c[i-1],b[i-2])] % mod* (ll)c[i-1] % mod + f[i-2]) %= mod;
ans = f[n];
printf("%d",ans);
return 0;
o (N)