洛谷 P2044 [NOI2012] 随机数生成器

题意

给定 \(m , a , c X_0 , n , g\) ,且满足 \(X_{n+1} = (a X_n + c) \quad mod \quad m\) , 求 \(X_n \quad mod \quad g\)

思路

矩阵快速幂加速递推方程的板子题

但是\(long \quad long\) 乘法会溢出 , 需要解决

两种办法 :

  1. 防溢出乘法

原理和快速幂差不多QAQ

  1. __int128

这个输出需要用快写

代码

防溢出乘法

#include<bits/stdc++.h>
using namespace std;
#define int long long int
inline int read() {
    int ans = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')f = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans * f;
}
int m,a,c,X0,n,g;
int mt[4][4],tmp[4][4],ans[4][4];

int cf(int a,int b) {
    int ans = 0;
    while (b) {
        if (b&1)
            ans = ( ans + a) % m;
        a = (a + a) %m;
        b>>=1;
    }
    return ans;
}
void mul() {
    for (int i = 1; i<=3; i++)
        for (int j =1; j<=3; j++) {
            for (int k = 1; k<=3 ;k++)
                tmp[i][j] = (tmp[i][j] + cf(mt[i][k], ans[k][j]))%m;

        }
    for (int i = 1; i<=3; i++)
        for (int j =1;j<=3;j++)
            ans[i][j] = tmp[i][j], tmp[i][j] = 0;
}

void selfmul() {
    for (int i = 1; i<=3; i++)
        for (int j =1; j<=3; j++) {
            for (int k = 1; k<=3 ;k++)
                tmp[i][j] = (tmp[i][j] +cf( mt[i][k] , mt[k][j]))%m;
        }
    for (int i = 1; i<=3; i++)
        for (int j =1;j<=3;j++)
            mt[i][j] = tmp[i][j], tmp[i][j] = 0;
}
void qmpow(int k) {
    while (k) {
        if (k&1) mul();
        selfmul();
        k >>=1;
    }
}

signed main() {
    m = read(),a=read(),c=read(),X0=read(),n=read(),g=read();
    mt[1][1] = a,mt[1][3] = c,mt[2][1] = 1,mt[3][3] = 1;
    for (int i = 1; i<=3;i++)ans[i][i] = 1;
    int x1 = (cf(a  , X0) + c) % m;
    qmpow(n);
    cout<<(cf(ans[2][1] ,x1)  + cf(ans[2][2], X0) + ans[2][3])%m % g;
    return 0;
}

__int128

#include<bits/stdc++.h>
using namespace std;
#define int __int128
inline int read() {
    int ans = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')f = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans * f;
}
int m,a,c,X0,n,g;
int mt[4][4],tmp[4][4],ans[4][4];
void mul() {
    for (int i = 1; i<=3; i++)
        for (int j =1; j<=3; j++) {
            for (int k = 1; k<=3 ;k++)
                tmp[i][j] = (tmp[i][j] + mt[i][k] * ans[k][j])%m;

        }
    for (int i = 1; i<=3; i++)
        for (int j =1;j<=3;j++)
            ans[i][j] = tmp[i][j], tmp[i][j] = 0;
}

void selfmul() {
    for (int i = 1; i<=3; i++)
        for (int j =1; j<=3; j++) {
            for (int k = 1; k<=3 ;k++)
                tmp[i][j] = (tmp[i][j] + mt[i][k] * mt[k][j])%m;
        }
    for (int i = 1; i<=3; i++)
        for (int j =1;j<=3;j++)
            mt[i][j] = tmp[i][j], tmp[i][j] = 0;
}
void qmpow(int k) {
    while (k) {
        if (k&1) mul();
        selfmul();
        k >>=1;
    }
}

void print(int a) {
    if (a==0){putchar('0'); return ;}
    if (a<0){putchar('-'),a=-a;}
    static int sta[50];
    int top = 0;
    while (a) {
        sta[++top] = a % 10;
        a/=10;
    }
    while (top)
        putchar(sta[top--] + '0');
}
signed main() {
    m = read(),a=read(),c=read(),X0=read(),n=read(),g=read();
    mt[1][1] = a,mt[1][3] = c,mt[2][1] = 1,mt[3][3] = 1;
    for (int i = 1; i<=3;i++)ans[i][i] = 1;
    int x1 = (a  * X0 + c) % m;
    qmpow(n);
    print((ans[2][1] *x1  + ans[2][2] * X0 + ans[2][3])%m % g);
    return 0;
}
posted @ 2025-04-21 21:56  Guaninf  阅读(14)  评论(0)    收藏  举报