码迷,mamicode.com
首页 > 其他好文 > 详细

【九校联考】锻造

时间:2018-10-19 10:15:28      阅读:264      评论:0      收藏:0      [点我收藏+]

标签:精通   垃圾   含义   mes   数组   cout   def   typename   col   

题目描述

“欢迎啊,老朋友。”

一阵寒暄过后,厂长带他们参观了厂子四周,并给他们讲锻造的流程。

“我们这里的武器分成若干的等级,等级越高武器就越厉害,并且对每一等级的武器都有两种属性值 b 和 c,但是我们初始只能花 a 个金币来生产 1 把 0 级剑……”

“所以你们厂子怎么这么垃圾啊,不能一下子就造出来 999 级的武器吗?”勇者不耐烦的打断了厂长的话。

“别着急,还没开始讲锻造呢……那我们举例你手中有一把 x 级武器和一把 y 级武器 (y = max(x?1,0)),我们令锻造附加值 k = min(c x ,b y ),则你有 k/cx 的概率将两把武器融合成一把 x + 1 级的武器。”

“……但是,锻造不是一帆风顺的,你同样有 1 ? k/cx 的概率将两把武器融合成一把 max(x ? 1,0) 级的武器……”

勇者听完后暗暗思忖,他知道厂长一定又想借此机会坑骗他的零花钱,于是求助这个村最聪明的智者——你,来告诉他,想要强化出一把 n 级的武器,其期望花费为多少?

由于勇者不精通高精度小数,所以你只需要将答案对 998244353(7 ×17 × 2 23 + 1,一个质数 ) 取模即可。


输入

第一行两个整数 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;
}


输出

输出一行一个整数,表示期望花费。


样例输入

0 6432
4602677 3944535 2618884 6368297 9477531


样例输出

6432

 



题解

成功的概率p1=k / c[ i-1 ],失败的概率p2= ( c[ i-1 ] - k ) / c[ i-1 ]。设dp[ i ]表示升到 i 级的期望花费 ,那么dp[ i ] = p1 * ( dp[ i-1 ] + dp[ i-2 ] ) + p2* ( dp[ i-1 ] + dp[ i ] )。移项化简:

dp[ i ] = dp[ i-1 ]+ dp[ i-2 ] + ( c[ i-1 ] - k ) * dp[ i-1 ] / k 。预处理k的逆元,递推一遍即可。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=1e7+50;
const int mod=998244353;

int n,a,bx,by,cx,cy,p,k,inv[maxn];
int b[maxn],c[maxn];
ll dp[maxn];

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<0||cc>9)&&cc!=-) cc=getchar();
    if(cc==-) ff=-1,cc=getchar();
    while(cc>=0&&cc<=9) aa=aa*10+cc-0,cc=getchar();
    aa*=ff;
}

ll qpow(ll a,ll b){
    ll ans=1;a%=mod;
    for(ll i=b;i;i>>=1,a=a*a%mod)
    if(i&1) ans=ans*a%mod;
    return ans;
}

void init(){
    inv[1]=1;
    for(int i=2;i<=maxn;i++)
    inv[i]=(ll)inv[mod%i]*(mod-mod/i)%mod;
}

int main(){
    freopen("forging.in","r",stdin);
    freopen("forging.out","w",stdout);
    read(n),read(a);
    read(bx),read(by),read(cx),read(cy),read(p);
    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;
    }
    init();
    dp[0]=a;
    k=min(c[0],b[0]);
    dp[1]=(2ll*k*a%mod+1ll*a*(c[0]-k+mod)%mod)%mod*inv[k]%mod;
    for(int i=2;i<=n;i++){
        k=min(c[i-1],b[i-2]);
        dp[i]=((dp[i-1]+dp[i-2])%mod+1ll*dp[i-1]*(c[i-1]-k+mod)%mod*inv[k]%mod)%mod;
    }
    cout<<dp[n]<<endl;
    return 0;
}

 

【九校联考】锻造

标签:精通   垃圾   含义   mes   数组   cout   def   typename   col   

原文地址:https://www.cnblogs.com/rlddd/p/9814336.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!