HDU 5490 Simple Matrix(组合数学+构造等比数列)——2015 ACM/ICPC Asia Regional Hefei Online

来源:互联网 发布:淘宝网的运营模式是() 编辑:程序博客网 时间:2024/05/19 23:17

传送门

Simple Matrix

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 471    Accepted Submission(s): 158


Problem Description
As we know, sequence in the form of an=a1+(n1)d is called arithmetic progression and sequence in the form of bn=b1qn1(q>1,b10) is called geometric progression. Huazheng wants to use these two simple sequences to generate a simple matrix. Here is what he decides to do:
Use the geometric progression as the first row of the simple matrix: c0,n=bn
Use the arithmetic progression as the first column of the simple matrix: cn,0=an
Calculate the item at n-th row, m-th column of the simple matrix as cn,m=cn1,m+cn,m1, where n1 and m1.
Given the two sequences, Huazheng wants to know the value of cn,m, but he is too busy with his research to figure it out. Please help him to work it out. By the way, you can assume that c0,0=0.
 

Input
The first line of input contains a number T indicating the number of test cases (T200).
For each test case, there is only one line containing six non-negative integers b1,q,a1,d,n,m. (0n10000). All integers are less than 231.
 

Output
For each test case, output a single line consisting of “Case #X: Y”. X is the test case number starting from 1. Y is cn,m module 1000000007.
 

Sample Input
2
3 10 1 1 3 3
5 2 1 10 4 2
 

Sample Output
Case #1: 423
Case #2: 140

题目大意:

就是给了一个矩阵,这个矩阵的第 0 行是等比数列(首项 b1 已知,公比 q 已知),第 0 列是等差数列(首项 a1 已知,

公差 d 已知),剩余的满足一个式子 c[i][j]=c[i1][j1]+c[i1][j], 现在求 c[n][m] % (109+7), 其中 n104,<231

解题思路:

这个题显然要分开求,意思就是先求等比数列的,再求等差数列的,等差数列可以通过找找规律就可以发现是一个类似杨辉三角的东西,重点是

解决等比数列的问题。因为 m 太大了,所以我们要想办法快速的计算第 m 列的值,那么只有等比数列可以快速的计算值,那么我们就想

办法构造一个等比数列,首先观察第 1 行和第 0 行的关系,然后发现第 1 行是第 0 行的求和,那么我们现在设一个表达式 F(i,j)

表示的是第 i 行 第 j 列的格子中的值,那么 F(1,j)=ji=0F(0,i) 还可以写成 F(1,j) = qF(1,j1)+b1 然后构造一个等比

数列 (F(1,j)+x) = q(F(1,j1)+x) 解得 x = b1q1 ,以此类推可以得到 n 个等比数列,那么我们现在多加了一项就在 an

的这个数列中减去,那么现在我们就是要求 ni=1aiC(n+m1i,ni)+b1qm+n1(q1)n

My Code:

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;typedef long long LL;const LL MOD = 1e9+7;const int MAXN = 1e6+5;void Exgcd(LL a, LL b, LL &x, LL &y){    if(b == 0){        x = 1;        y = 0;        return;    }    LL x1, y1;    Exgcd(b, a%b, x1, y1);    x = y1;    y = x1 - (a/b)*y1;}LL pow_mod(LL a, LL b){    LL ans = 1;    while(b){        if(b & 1)            ans = (ans*a) % MOD;        b>>=1LL;        a = (a*a) % MOD;    }    return ans;}LL suma[MAXN];///等差数列的第一项int main(){    ///freopen("in.txt","r",stdin);    int T;    scanf("%d",&T);    for(int cas=1; cas<=T; cas++){        LL b1, q, a1, d, n, m;        scanf("%lld%lld%lld%lld%lld%lld",&b1,&q,&a1,&d,&n,&m);        if(n==0 && m==0){            printf("Case #%d: %0\n",cas);            continue;        }        b1 %= MOD, q %= MOD;        a1 %= MOD, d %= MOD;        LL now = b1, x, y, tmp;        for(LL i=1; i<=n; i++){            Exgcd(q-1, MOD, x, y);            x = (x % MOD + MOD) % MOD;            x = now*x%MOD;///now / (q-1)            now = (now + x) % MOD;            suma[i] = (a1 + (i-1)*d%MOD - x);            suma[i] = (suma[i] % MOD + MOD) % MOD;        }        /**等比数列的 start**/        Exgcd(q-1, MOD, x, y);        LL Inv = (x % MOD + MOD) % MOD;        LL ans = pow_mod(Inv, n);        x = pow_mod(q, m+n-1);        ans = (ans * x % MOD) * b1 % MOD;        /**等比数列的 end**/        ans = (ans + suma[n]) % MOD;///特判一下        tmp = 1;        for(LL i=n-1; i>0; i--){            Exgcd(n-i, MOD, x, y);            x = (x % MOD + MOD) % MOD;            x = (x *((n+m-1)-i))%MOD;            tmp = tmp * x % MOD;            ans = (ans + tmp*suma[i]%MOD) % MOD;        }        printf("Case #%d: %lld\n",cas,ans);    }    return 0;}
0 0
原创粉丝点击