• NOI2012 随机数生成器


    题意:

    给定$x,y,n,a_{0},m,g$.

    定义$a_{i}=x*a_{i-1}+y mod m$

    求$a_{n} mod g$

    $n,m,x,y,a<=10^{18},g<=10^{8}$

    题解:

    当n较小,可以直接算出$a_{n}$

    可以得到$a_{n}$的通项公式  $a_{n}=x^{n}*a_{0}+y*frac{x^{n-1}-1}{x-1}$

    当m是素数时,可以通过求解逆元得到结果.

    对于没有特殊性质的数据该怎么做?

    我们可以把递推式构造成矩阵

    $egin{Bmatrix} a_{i} \ y end{Bmatrix}  = egin{Bmatrix} x & 1 \ 0 & 1 end{Bmatrix} * egin{Bmatrix} a_{i-1} \ y end{Bmatrix} $

    那就可以再$logn$内求出$a_{n}$

    但是注意 $m$是LL范围的,所以中间结果可能会溢出.

    对于这种情况 可以使用"快速乘" 用快速幂的思路把乘法转化成加法.这样就可以实现LL乘法了.

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define ll long long
    ll n,m,g,x,y,a;
    void Add(ll &x,ll y){x+=y;if(x>=m)x-=m;}
    ll mul(ll a,ll b){
        ll res=0;
        while(b){
            if(b&1)Add(res,a);
            Add(a,a);
            b>>=1;
        }
        return res;
    }
    struct Mat{
        int a,b;
        ll c[2][2];
        Mat(){c[0][0]=c[0][1]=c[1][0]=c[1][1]=0;}
        Mat operator*(const Mat &tmp)const{
            Mat t;
            for(int i=0;i<a;i++){
                for(int j=0;j<tmp.b;j++)
                    for(int k=0;k<b;k++)
                        Add(t.c[i][j],mul(c[i][k],tmp.c[k][j]));
            }
            t.a=a,t.b=tmp.b;
            return t;
        }
        void init(int x,int y){
            a=x,b=y;
        }
    }I;
    ll calc(){
        ll b=n;
        Mat t;t.init(2,2);
        t.c[0][0]=x,t.c[0][1]=t.c[1][1]=1;
        I.init(2,1);
        I.c[0][0]=a;
        I.c[1][0]=y;
        while(b){
            if(b&1)I=t*I;
            t=t*t;
            b>>=1;
        }
        return I.c[0][0];
    }
    int main(){
    //    freopen("random.in","r",stdin);
        cin>>m>>x>>y>>a>>n>>g;
        x%=m,y%=m,a%=m;
        cout<<calc()%g<<endl;
        return 0;
    }
    View Code

    $By LIN452$

    $2017.06.09$

  • 相关阅读:
    linux基础命令:alias
    linux基础命令:find
    Linux下which、whereis、locate命令的区别
    逆元知识普及(进阶篇) ——from Judge
    BZOJ 3620: 似乎在梦中见过的样子
    HDU contest808 ACM多校第7场 Problem
    P3203 [HNOI2010]弹飞绵羊 —— 懒标记?分块?LCT?...FAQ orz
    可持久化数组(线段树)[模板题]
    可持久化并(xian)查(duan)集(shu)
    主席树(静态)的轻松入门
  • 原文地址:https://www.cnblogs.com/Lay-with-me/p/6971981.html
Copyright © 2020-2023  润新知