6271. 2019.8.4【NOIP提高组A】锻造 (forging)

本文解析了一道关于锻造物品的NOIP提高组A类题目,通过概率论计算锻造特定等级物品的期望花费,介绍了如何使用动态规划和逆元求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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。

期望次数  = \frac{_{1}}{P}  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)

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值