博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[JZOJ6271] 2019.8.4【NOIP提高组A】锻造
阅读量:5292 次
发布时间:2019-06-14

本文共 1467 字,大约阅读时间需要 4 分钟。

题目大意

武器的每个级别有固定的两种属性\(b_i\)\(c_i\)

可以用\(a\)的代价得到一把\(0\)级的武器。
可以将\(x\)级武器和\(y=\max(x-1,0)\)级武器融合锻造,
\(\frac{\min(b_y,c_x)}{c_x}\)的概率可以升级成\(x+1\)级武器。
反之降级成\(y\)级武器。
问得到\(n\)级武器的期望代价(模意义下)。


思考历程

一开始想了个特别简单的DP。

然后发现有后效性……
搞不出来,然后心态崩了……
看到\(p=0\)的情况(也就是除了\(i=0\)之外,其它时候的\(b_i\)\(c_i\)都为\(1\),也就是百分百成功率)。
这样就可以特殊计算\(f_0\)\(f_1\),后面的像斐波拉契数列一样转移就可以了。


正解

正解的DP是没有后效性的。

正解的DP的目光更加长远,我想到的只是转移了一步的,但是正解是转移了很多步的。
状态还是\(f_i\)表示造\(i\)级武器的期望代价。
设成功率为\(x\),则方程为\(f_i=f_{i-2}+f_{i-1}+(1-x)(f_i-f_{i-2})\)
前面半段是锻造的代价,后面是没有成功时的代价。
由于没有成功的时候还可以有\(i-2\)级的武器留下来,所以就在下一次锻造的时候将它的代价减去。
方程移项之后显然是没有后效性的。

然而这题卡时间。

比如要打\(O(n)\)求逆元,还有各种小常数优化。


代码

卡常数卡到极尽的代码

using namespace std;#include 
#include
#include
#define N 10000010#define mo 998244353int n,a;int bx,by,cx,cy,p;int inv[N],f[N];int main(){ freopen("forging.in","r",stdin); freopen("forging.out","w",stdout); scanf("%d%d%d%d%d%d%d",&n,&a,&bx,&by,&cx,&cy,&p); inv[1]=1; for (register int i=2,k;i<=p;++i){ k=mo/i; inv[i]=(long long)(mo-k)*inv[mo-i*k]%mo; } int b=by+1,c=cy+1; f[0]=a; f[1]=(f[0]+(long long)f[0]*(b>=c?1:(long long)inv[b]*c%mo))%mo; for (register int i=2;i<=n;++i){ c=((long long)c*cx+cy)%p+1; f[i]=(f[i-2]+(long long)f[i-1]*(b>=c?1:(long long)inv[b]*c%mo))%mo; b=((long long)b*bx+by)%p+1; } printf("%d\n",f[n]); return 0;}

总结

做期望DP的时候,目光一定要长远,从而避免后效性。

转载于:https://www.cnblogs.com/jz-597/p/11298800.html

你可能感兴趣的文章
模运算
查看>>
python多线程的使用
查看>>
团队编程项目作业1-成员简介及分工
查看>>
使用Chrome(PC)调试移动设备上的网页
查看>>
UI基础--手写代码实现汤姆猫动画
查看>>
使用gitbash来链接mysql
查看>>
黑盒测试和百合测试的优缺点对比
查看>>
SecureCRT的使用方法和技巧(详细使用教程)
查看>>
右侧导航栏(动态添加数据到list)
查看>>
81、iOS本地推送与远程推送详解
查看>>
C#基础_注释和VS常用快捷键(一)
查看>>
虚拟DOM
查看>>
uva 11468 Substring
查看>>
自建数据源(RSO2)、及数据源增强
查看>>
BootStrap2学习日记2--将固定布局换成响应式布局
查看>>
关于View控件中的Context选择
查看>>
2018icpc徐州OnlineA Hard to prepare
查看>>
R语言-rnorm函数
查看>>
Spark的启动进程详解
查看>>
Java 字符终端上获取输入三种方式
查看>>