• 【JZOJ6271】【NOIP提高组A】锻造 (forging)


    题目大意

    有如下两个操作

    • 花费(a)购买一把(0)级的剑
    • 将一把(x)级的剑与一把(max(x-1,0))级的剑进行锻造,有(p)的概率成功,然后得到一把(x+1)级的剑,若失败,得到一把(max(x-1,0))级的剑
      求得到一把(n)级的剑的期望花费。

    分析

    首先明确一点,假如你要得到(x)级的剑,不用考虑它是失败后得到的(因为你有了(x)还和(x+1)去锻造不是白给吗?(逐渐茄化)),因此只用考虑(x)(x-1)(x-2)锻造得来的期望花费。

    (f_i)表示弄到一把(i)级的剑的期望花费,得到递推式:

    [f_i=f_{i-2}+f_{i-1}+sum_{k=1}^{infty}(1-p)^k f_{i-1} ]

    这个式子怎么解释呢?你想锻造(i),弄到(i-1)(i-2)的花费是必不可少的,若你失败了,(i-2)还在,你要买的只是(i-1)。你可以失败无数次,于是就得到上面的式子。一波化简后得到:

    [f_i=f_{i-2}+frac{f_{i-1}}{p} ]

    线性求逆元然后优化优化常数就是一道好题了。

    Code

    #include <cstdio>
    
    typedef long long ll;
    const int N = 10000007, P = 998244353;
    int min(int a, int b)
    {
    	if (a < b) return a;
    	return b;
    }
    
    int n, a, bx, by, cx, cy, p, u, v, w, i, k;
    int b[N], c[N], inv[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);
    	b[0] = by + 1, c[0] = cy + 1;
    	for (i = 1; i < n; ++i) b[i] = (1ll * b[i - 1] * bx % p + by) % p + 1, c[i] = (1ll * c[i - 1] * cx % p + cy) % p + 1;
    	inv[1] = 1; for (i = 2; i <= p; ++i) inv[i] = 1ll * inv[P % i] * (P - P / i) % P;
    	u = a, v = (u + 1ll * u * inv[min(c[0], b[0])] % P * c[0] % P) % P;
    	if (n == 0) printf("%d
    ", u);
    	else
    	{
    		for (i = 2, k; i <= n; ++i) k = min(c[i - 1], b[i - 2]), w = (u + 1ll * v * inv[k] % P * c[i - 1] % P) % P, u = v, v = w;
    		printf("%d
    ", v);
    	}
    	return 0;
    }
    
  • 相关阅读:
    获取当前季的js
    C#获取文件大小
    SQL Server 2005 Express Edition 傻瓜式安装
    SET XACT_ABORT ON
    Resignation letter
    Exchange Web Services Managed API 1.0 入门
    Please let us know in case of any issues
    33条C#、.Net经典面试题目及答案
    c# 修饰词public, protected, private,internal,protected的区别
    EXEC DTS
  • 原文地址:https://www.cnblogs.com/zjlcnblogs/p/11300028.html
Copyright © 2020-2023  润新知