【JZOJ6271】锻造 (forging)

65 篇文章 2 订阅
11 篇文章 0 订阅
这篇博客探讨了在特定条件下锻造剑的概率问题。博主首先分析了当p=1时,从两把0级剑合成1级剑的期望值,并通过数列知识或打表发现其规律。接着,博主定义了f[i]为合成i级剑的期望,并给出递推公式f[i]=pf[i−1]+f[i−2],用于计算100点积分情况下的期望值。博客中提到,如果合成失败,会得到一把i-2级的剑,减少了下次合成的难度。博主以代码的形式展示了这一过程,并反思了思考问题的深度,鼓励自己更深入地研究以获取更高的分数。
摘要由CSDN通过智能技术生成

description


analysis

  • 首先看一下 p = 1 p=1 p=1,即 1 1 1以后的合成一定成功的情况

  • 如果按照求期望值的一般做法求两把 0 0 0合成 1 1 1的期望,会画出一棵无穷大的树

  • 这个的期望值就是 a + ∑ i = 1 ∞ a p ( 1 − p ) i − 1 a+\sum^{∞}_{i=1}ap(1-p)^{i-1} a+i=1ap(1p)i1

  • 通过数列知识或者打表找规律可以知道这个值为 a + a p a+{a\over p} a+pa(或者说是 f [ 0 ] + f [ 0 ] p f[0]+{f[0]\over p} f[0]+pf[0]

  • f [ i ] f[i] f[i]为合成一把 i i i级剑的期望, f [ 1 ] f[1] f[1]单独计算,后面的 f [ i ] = f [ i − 1 ] + f [ i − 2 ] f[i]=f[i-1]+f[i-2] f[i]=f[i1]+f[i2]

  • 扩展到 100 p t s 100pts 100pts的情况,如果 i i i级剑合成失败了,会产生一把 i − 2 i-2 i2级的剑

  • 也就是说下一次合成 i i i级剑,只需要合成 i − 1 i-1 i1级剑,不需要再搞来一把 i − 2 i-2 i2级剑

  • 同理再画一棵期望树,每次成功的代价是 f [ i − 1 ] f[i-1] f[i1],一开始就有的代价是 f [ i − 2 ] f[i-2] f[i2]

f [ i − 2 ] + ∑ i = 1 ∞ f [ i − 1 ] p ( 1 − p ) i − 1 f[i-2]+\sum_{i=1}^∞f[i-1]p(1-p)^{i-1} f[i2]+i=1f[i1]p(1p)i1

  • 根据已知的规律,所以 f [ i ] = f [ i − 1 ] p + f [ i − 2 ] f[i]={f[i-1]\over p}+f[i-2] f[i]=pf[i1]+f[i2]

  • 下次要好好动脑, 60 p t s 60pts 60pts都想出来了,要想再深入一点,争取拿分


code

#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 max(x,y) ((x>y)?(x):(y))
#define min(x,y) ((x<y)?(x):(y))
#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;
ll tmp;

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;
}
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;
		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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值