[BZOJ 2875][Noi2012]随机数生成器:矩阵乘法+快速乘

快速乘法解决大数乘法问题
本文介绍了一个利用快速乘法解决大数乘法溢出问题的C++实现方案。通过矩阵快速幂的方法避免了longlong类型直接相乘可能导致的数值溢出,适用于处理不超过1e18的大数运算。

点击这里查看原题

其实是个水题,坑点在于两个long long直接相乘会爆。long long的上限大概是2*1e18,而题目所给的数据不会超过1e18,因此可以使用快速乘。

/*
User:Small
Language:C++
Problem No.:2875
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
ll m,a,c,x,n,g;
struct mat{
    ll n,m,c[4][4];
    mat(){
        memset(c,0,sizeof(c));
    }
}f,b;
ll mul(ll a,ll b){
    ll res=0;
    while(b){
        if(b&1LL) res=(res+a)%m;
        a=(a+a)%m;
        b>>=1LL;
    }
    return res;
}
mat operator*(const mat a,const mat b){
    mat c;
    c.n=a.n;
    c.m=b.m;
    for(int i=1;i<=c.n;i++)
        for(int j=1;j<=c.m;j++)
            for(int k=1;k<=a.m;k++)
                c.c[i][j]=(c.c[i][j]+mul(a.c[i][k],b.c[k][j]))%m;
    return c;
}
mat pow(mat a,ll b){
    mat res;
    res.n=res.m=a.n;
    for(int i=1;i<=res.n;i++) res.c[i][i]=1;
    while(b){
        if(b&1LL) res=res*a;
        a=a*a;
        b>>=1LL;
    }
    return res;
}
int main(){
    freopen("data.in","r",stdin);//
    scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&x,&n,&g);
    f.n=1,f.m=2;
    f.c[1][1]=x;
    f.c[1][2]=c;
    b.n=b.m=2;
    b.c[1][1]=a;
    b.c[2][1]=b.c[2][2]=1;
    mat ans=f*pow(b,n);
    printf("%lld\n",ans.c[1][1]%g);
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值