【组合数学 && dp[i][j] = a*dp[i, j-1] + b*dp[i-1,j]+c 求 dp[n][n]】Gym - 101480F Frightful Formula

本文探讨了在特定条件下的矩阵乘法与动态规划问题,给出了一种求解dp[n][n]的方法,通过初始化、预处理阶乘及其逆元,结合组合数计算,最终在给定的数据范围内实现了高效求解。

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

Step1 Problem:

已知 a,b,ca, b, ca,b,cdp[k][1],dp[1][k]dp[k][1], dp[1][k]dp[k][1],dp[1][k] 其中 k=1,2,3,...,n.k = 1, 2, 3, ..., n.k=1,2,3,...,n.
dp[i][j]=a∗dp[i][j−1]+b∗dp[i−1][j]+c;dp[i][j] = a*dp[i][j-1] + b*dp[i-1][j] + c;dp[i][j]=adp[i][j1]+bdp[i1][j]+c;
dp[n][n]dp[n][n]dp[n][n].
数据范围:
2&lt;=n&lt;=200000,0&lt;=a,b,c&lt;=1e6.2 &lt;= n &lt;= 200000, 0 &lt;= a, b, c &lt;= 1e6.2<=n<=200000,0<=a,b,c<=1e6.

Step2 Ideas:
(待填)

Step3 Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5+5;
const int MOD = 1e6+3;
int row[N], col[N];
ll ap[N], bp[N], A[2*N], inv[2*N];
ll Pow(ll x, int n)
{
    ll ans = 1;
    while(n)
    {
        if(n&1) ans *= x, ans %= MOD;
        x = x*x, x %= MOD;
        n >>= 1;
    }
    return ans;
}
void init()
{
    A[1] = inv[1] = 1;
    ll ans = 1;
    int n = 2*N;
    for(int i = 2; i < n; i++) {
        ans *= i, ans %= MOD;
        A[i] = ans;
        inv[i] = Pow(ans, MOD-2);
    }
}
ll C(int n, int m)
{
    if(m == n || m == 0) return 1;
    return A[n]*inv[n-m]%MOD*inv[m]%MOD;
}
int main()
{
    init();
    int n, a, b, c;
    scanf("%d %d %d %d", &n, &a, &b, &c);
    ap[0] = bp[0] = 1;
    for(int i = 1; i <= n; i++) {
        ap[i] = ap[i-1]*a, ap[i] %= MOD;
        bp[i] = bp[i-1]*b, bp[i] %= MOD;
    }
    for(int i = 1; i <= n; i++)
        scanf("%d", row+i);
    for(int i = 1; i <= n; i++)
        scanf("%d", col+i);
    if(a == 0 && b == 0) {
        printf("%d\n", c);
    }
    else if(a == 0) {
        ll ans = col[n];
        for(int i = 2; i <= n; i++) {
            ans = ans * b + c;
            ans %= MOD;
        }
        printf("%lld\n", ans);
    }
    else if(b == 0) {
        ll ans = row[n];
        for(int i = 2; i <= n; i++) {
            ans = ans * a + c;
            ans %= MOD;
        }
        printf("%lld\n", ans);
    }
    else {
//        double k = 1.0*c/(a+b-1);
//        double ans = 0;
        ll ans = 0;
        ll tmp = Pow(a+b-1, MOD-2);
        for(int i = 2; i <= n; i++) {
            ans += (row[i]+c*tmp)%MOD*C(n-i+n-2, n-i)%MOD * ap[n-1]%MOD * bp[n-i]%MOD, ans %= MOD;
        }
        for(int i = 2; i <= n; i++) {
            ans += (col[i]+c*tmp)%MOD*C(n-i+n-2, n-i)%MOD * ap[n-i]%MOD * bp[n-1]%MOD, ans %= MOD;
        }
        printf("%lld\n", ((ans - c*tmp)%MOD + MOD)%MOD);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值