FZU 1692 Key problem(构造矩阵+矩阵快速幂)

来源:互联网 发布:彩电销售最优化问题 编辑:程序博客网 时间:2024/06/05 07:53

【题目链接】点击打开FZU 1692

【题意】:1 题目的意思是有n个人构成一个圈,每个人初始的有ai个苹果,现在做m次的游戏,每一次游戏过后第i个人能够增加R*A(i+n-1)%n+L*A(i+1)%n 个苹果(题目有错),问m轮游戏过后每个人的苹果数

【思路】:

根据题目的意思我们能够列出一轮过后每个人的苹果数

   a0 = a0+R*an-1+L*a1

   a1 = a1+R*a0+L*a2

   .............................

   an-1 = an-1+R*an-2+L*a0

3 根据第二条思路我们可以构造出如下的矩阵

   1 L 0 ...... R        a0         a0'

   R 1 L .........  *     a1         a1'

   ...................       ....      = ......

   ...........R 1 L      an-2       an-2'

   L ...........R 1      an-1       an-1'

4 那么根据3我们可以利用矩阵快速幂求出最后的答案,但是题目的n最大为100,m最大为10^9,那么每个case的时间复杂度为O(Logm*n^3),当n最大为100的时候是会TLE的

5 我们发现初始的矩阵里面,矩阵是一个循环同构的,就是说矩阵的每一行度能够从上一行推出,那么我们只要利用O(n^2)的时间求出第一行,然后我们在利用递推求出剩下的n-1行,那么总的时间复杂度为O(Logm*n^2)

代码:

/*Problem id. FZU 1692RunID: 631373UserID: ACM_herongweiSubmit time: 2015-09-04 11:58:16Language: C++Length: 1806 Bytes.Result: Accepted*/#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int N=105;int arr[N];int n,m,L,R,MOD;struct mut{    LL mat[N][N];    mut()    {        memset(mat,0,sizeof(mat));    }    void init()    {        for(int i=0; i<n; ++i)        {            mat[i][(i+n-1)%n]=L;            mat[i][i]=1;            mat[i][(i+1)%n]=R;        }    }};mut multi(mut &a,mut &b){    mut c;    for(int i=0; i<n; ++i)    {        if(a.mat[0][i])        {            for(int j=0; j<n; ++j)            {                if(b.mat[i][j])                {                    c.mat[0][j]=(c.mat[0][j]+a.mat[0][i]*b.mat[i][j])%MOD;                }            }        }    }    for(int i = 1; i < n; i ++)    {        c.mat[i][0] = c.mat[i - 1][n - 1];        for(int j = 1; j <n; j ++)            c.mat[i][j] = c.mat[i - 1][j - 1];    }    return c;}mut poww(mut unit, mut a,int n){    while(n)    {        if(n&1) unit=multi(unit,a);        a=multi(a,a);        n>>=1;    }    return unit;}void solve(){    int ans=0;    mut unit,a;    scanf("%d %d %d %d %d",&n,&m,&R,&L,&MOD);    for(int i=0; i<n; ++i)    {        scanf("%d",&arr[i]);        unit.mat[i][i]=1;    }    a.init();    unit=poww(unit,a,m);    for(int i=0; i<n; ++i)    {        ans=0;        for(int j=0; j<n; ++j)        {            if(unit.mat[i][j]&&arr[j])                ans+=(unit.mat[i][j]*arr[j])%MOD;        }        if(i) printf(" ");        printf("%d",ans%MOD);    }    puts("");}int main(){    int t;    scanf("%d",&t);    while(t--)    {        solve();    }    return 0;}


0 0