旅途

题目描述

小象来到了百特国旅游。百特国有 nn 所城市,这些城市围成了一个圈。小象按照顺时针给这些城市从 11 到 nn 编号,其中 11 号城市是他最先到达的城市。

小象患有选择困难症。他在旅游之前并没有制定合理的旅游计划,而是决定用一个随机策略来访问这些城市。

小象共有 mm 天的旅游时间。在第一天里,小象会选择游玩 11 号城市。而在接下来的每一天,他有 p\%p% 的概率去前一天游玩城市顺时针方向的下一个城市游玩,有 q\%q% 的概率去逆时针方向的下一个城市游玩,也有 (100 - p - q)\%(100pq)% 的概率继续停留在前一天的城市游玩。

他很好奇他平均可以游玩到多少个不同的城市,你可以帮他计算一下吗?不妨设他能恰好游玩到 ii 个城市的概率是 f(i)f(i),在给定正整数 kk 的情况下,请你计算 100^{m - 1} sumlimits_{i = 1}^{n}{i^k f(i)}100m1i=1nikf(i) 对 (10^9 + 7)(109+7) 取模的值。

不难证明 100^{m - 1} sumlimits_{i = 1}^{n}{i^k f(i)}100m1i=1nikf(i) 是一个整数,它对 (10^9 + 7)(109+7) 取模的值也是明确的、良定义的。

输入描述

输入包含多组测试数据。输入的第一行包含一个正整数 TT (1 leq T leq 5001T500),表示测试数据的组数。接下来依次描述每组测试数据,对于每组测试数据:

仅一行,包含五个整数 nn, mm, kk, pp 和 qq (1 leq n, m, k leq 5001n,m,k500, p, q geq 0p,q0, p + q leq100p+q100),含义如题面所示。

保证所有测试数据的 nn 之和不超过 10001000,所有测试数据的 mm 之和不超过 10001000。

输出描述

对于每组数据,输出一行,包含一个整数,表示所求的值。

样例输入 

3
5 5 1 25 25
5 5 2 50 50
5 5 3 0 100

样例输出

246093750
212499993
499999916

解题思路:对区间的左右端点进行dp

#include <bits/stdc++.h>
using namespace std;
#define N 505
int dp[N][N][N];  //dp[i][j][k],i:天数 j:离左端点距离 k:离右端点距离 
const int mod=1e9+7;
typedef long long ll;
ll quick(ll n,ll m)
{
    ll ans=1;
    n=n%mod;
    while(m>0)
    {
        if(m&1) ans=(ans*n)%mod;
        n=(n*n)%mod;
        m>>=1;
    }
    return ans;
}
int main()
{
    int n,m,k,T;
    scanf("%d",&T);
    while(T--)
    {
        int p,q;
        scanf("%d%d%d%d%d",&n,&m,&k,&p,&q);
        int t=(100-p-q);
        for(int i=0;i<=m;i++)
        {
            for(int j=0;j<=i;j++)
            {
                for(int k=0;k<=i;k++) dp[i][j][k]=0;
            }
        }
        dp[1][0][0]=1;
        for(int i=2;i<=m;i++)
        {
            for(int j=0;j<=i;j++)
            {
                for(int k=0;k<=i;k++)
                {
                    dp[i][j][k]=(dp[i][j][k]+1LL*t*dp[i-1][j][k]%mod)%mod;  //原地不动
                    dp[i][max(j-1,0)][k+1]=(dp[i][max(j-1,0)][k+1]+1LL*dp[i-1][j][k]*p%mod)%mod;//顺时针 
                    dp[i][j+1][max(k-1,0)]=(dp[i][j+1][max(k-1,0)]+1LL*dp[i-1][j][k]*q%mod)%mod;//逆时针 
                
                }
            }
        }
        int res=0;
        for(int i=0;i<=m;i++)
        {
            for(int j=0;j<=m;j++)
            {
                if(i+j+1<=n)
                res=(res+1LL*quick(i+j+1,k)%mod*dp[m][i][j])%mod;
                else res=(res+1LL*quick(n,k)%mod*dp[m][i][j])%mod;
            }
        }
        printf("%d
",res);
    }
}

原文地址:https://www.cnblogs.com/ww123/p/10651833.html