【codevs1281】Xn数列,矩阵乘法练习

时间限制: 1 s
空间限制: 128000 KB
题目等级 : 大师 Master
题解
题目描述 Description
给你6个数,m, a, c, x0, n, g

Xn+1 = ( aXn + c ) mod m,求Xn

m, a, c, x0, n, g<=10^18

输入描述 Input Description
一行六个数 m, a, c, x0, n, g

输出描述 Output Description
输出一个数 Xn mod g

样例输入 Sample Input
11 8 7 1 5 3

样例输出 Sample Output
2

数据范围及提示 Data Size & Hint
int64按位相乘可以不要用高精度。

写在前面:数论!数论!
思路:
转移矩阵:
{a,1}
{0,1}
初始矩阵:
{Xn}
{ c }
要加一个无聊的乘法优化,要不会炸longlong

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL m,a,c,x0,n,g;
struct matrix
{
    LL map[3][3];
    void clear(){memset(map,0,sizeof(map));}
};
LL cheng(LL x,LL y)//乘法优化,参照快速幂
{
    LL ans=0;
    while (y)
    {
        if (y&1) ans=(ans+x)%m;
        x=(x+x)%m;
        y>>=1;
    }
    return ans;
}
matrix mul(matrix x,matrix y)//矩阵乘法
{
    matrix z;
    z.clear();
    for (int i=1;i<=2;i++)
    for (int j=1;j<=2;j++)
    for (int k=1;k<=2;k++)
    z.map[i][j]=(z.map[i][j]+cheng(x.map[i][k],y.map[k][j])%m)%m;
    return z;
}
main()
{
    scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&x0,&n,&g);
    matrix x,ans;//ans为初始,x为转移
    x.clear();
    ans.clear();
    ans.map[1][1]=x0;
    ans.map[2][1]=c;
    x.map[1][1]=a;
    x.map[1][2]=1;
    x.map[2][1]=0;
    x.map[2][2]=1;
    while (n)
    {
        if (n&1) ans=mul(x,ans);
        x=mul(x,x);
        n>>=1;
    }
    printf("%lld",ans.map[1][1]%g);
}

你可能感兴趣的:(【codevs1281】Xn数列,矩阵乘法练习)