zoukankan      html  css  js  c++  java
  • bzoj4471 bzoj4490 随机数生成器Ⅱ

    Description

    继NOI2014后,小H又发现了一种新的生成随机数的方法。
    首先,给定三个随机种子P,C1,C2(C1≤C2)生成一个序列{xi},{xi}满足
    对于任意的i≥0,满足以下递推式Xi+2=(Xi+1+Xi) mod P
    其中x0=C1, x1=C2。
    接着,利用序列{xi},可以生成一个序列{ai}。序列{ai}的生成方式如下
    对于任意的i≥1,ai=∑xj^2(0≤j≤i) mod P
    然后,给定一个正整数Q,小H会进行Q次下述操作:每次选定两个正整数x, y,将ax和ay互换。
    小H希望检验一下序列{ai}是否是随机的。他还是希望使用NOI2014那道题的方法,生成一个N×M的矩阵,其中N表示行,M表示列。我们记这个矩阵为D,在D的第1行依次放入a1~aM,第2行放入aM+1~a2M,以此类推,那么矩阵D的第i行第j列的数Di,j就应该为a(i-1)*M+j。然后,类似方格取数,从矩阵的左上角(1,1)走到右下角(N,M),途中只能向右走或者向下走,这样他经过的方格数就应该是(N+M-1)。然后按照经过的顺序将每个方格的数字提取出来,组成一个序列叫做路径序列。他想知道,自己能得到的字典序最小的路径序列是什么。注意:为了方便,如果当前格向下和向右的方格的数字相同,那么我们认为向下的方格的数字小于向右的方格的数字。

    Input

    输入的第一行为六个正整数N,M,Q,P,C1,C2。意义见题目描述。
    接下来的Q行,每行一个操作:包含两个正整数x, y。

    Output

    输出一行,共(N+M-1)个正整数,表示字典序最小的路径序列。

    令F[-1]=1,F[0]=0,F[i]=F[i-1]+F[i-2](i>0)

    易证a[i](初始)=(c1^2*(F[n]*F[n-1]+1)+c2^2*F[n]*F[n+1]+2*c1*c2*(n为偶数?F[n]^2:F[n-1]*F[n+1]))mod p

    斐波那契数列可以用倍增O(logn)求出

    字典序最小可以贪心

    4471:

    #include<cstdio>
    typedef long long i64;
    int n,m,q,P,c1,c2;
    inline int read(){
        int x=0,c=getchar();
        while(c>57||c<48)c=getchar();
        while(c>47&&c<58)x=x*10+c-48,c=getchar();
        return x;
    }
    inline i64 read64(){
        i64 x=0;
        int c=getchar();
        while(c>57||c<48)c=getchar();
        while(c>47&&c<58)x=x*10+c-48,c=getchar();
        return x;
    }
    int stk[32],stp=0;
    int print(int x){
        if(!x)stk[stp++]=0;
        while(x)stk[stp++]=x%10,x/=10;
        for(int i=stp-1;i>=0;i--)putchar(stk[i]+48);
        stp=0;
    }
    inline void cal(int a,int b,int c,int d,int&e,int&f){
        e=(i64(b-a)*c+i64(a)*d)%P;
        f=(i64(a)*c+i64(b)*d)%P;
        if(e<0)e+=P;
        if(f<0)f+=P;
    }
    struct Seq_A{
        int as[100],bs[100];
        i64 c12,c22,c1c2;
        void init(){
            as[0]=1,bs[0]=1;
            for(int i=1;i<90;i++)cal(as[i-1],bs[i-1],as[i-1],bs[i-1],as[i],bs[i]);
            c12=i64(c1)*c1%P;
            c22=i64(c2)*c2%P;
            c1c2=i64(c1)*c2*2%P;
        }
        int operator[](i64 x){
            i64 v1,v2,v3;
            bool d=x&1;
            --x;
            int a=0,b=1;
            for(int i=0;x;i++,x>>=1)if(x&1)cal(a,b,as[i],bs[i],a,b);
            v1=a;v2=b;v3=a+b;
            if(d)return ((v1*v2+1)%P*c12%P+v2*v3%P*c22%P+v1*v3%P*c1c2%P)%P;
            return ((v1*v2+1)%P*c12%P+v2*v3%P*c22%P+v2*v2%P*c1c2%P)%P;
        }
    }a0;
    namespace Map{
        const int p=1844677;
        i64 xs[p];
        int ys[p];
        bool ed[p];
        int&get(i64 x){
            unsigned int w=x%p;
            while(ed[w]){
                if(xs[w]==x)return ys[w];
                w+=1237;
                if(w>=p)w-=p;
            }
            ed[w]=1;
            xs[w]=x;
            ys[w]=a0[x];
            if(ys[w]<0)ys[w]+=P;
            return ys[w];
        }
    }
    int main(){
        n=read();m=read();q=read();P=read();c1=read();c2=read();
        a0.init();
        for(int i=0;i<q;i++){
            i64 a=read64(),b=read64();
            int&a1=Map::get(a),&a2=Map::get(b),a3;
            a3=a1;a1=a2;a2=a3;
        }
        int xp=1,yp=1,ans;
        print(Map::get(1));
        while(xp<n||yp<m){
            if(xp==n)++yp;
            else if(yp==m)++xp;
            else{
                int a1=Map::get(i64(xp)*m+yp),a2=Map::get(i64(xp-1)*m+yp+1);
                if(a1<a2)++xp;
                else ++yp;
            }
            putchar(32);
            print((Map::get(i64(xp-1)*m+yp)+P)%P);
        }
        return 0;
    }

     4490:

    #include<cstdio>
    typedef long long i64;
    int n,m,q,P,c1,c2;
    inline int read(){
        int x=0,c=getchar();
        while(c>57||c<48)c=getchar();
        while(c>47&&c<58)x=x*10+c-48,c=getchar();
        return x;
    }
    inline i64 read64(){
        i64 x=0;
        int c=getchar();
        while(c>57||c<48)c=getchar();
        while(c>47&&c<58)x=x*10+c-48,c=getchar();
        return x;
    }
    inline void cal(int a,int b,int c,int d,int&e,int&f){
        e=(i64(b-a)*c+i64(a)*d)%P;
        f=(i64(a)*c+i64(b)*d)%P;
        if(e<0)e+=P;
        if(f<0)f+=P;
    }
    struct Seq_A{
        int as[100],bs[100];
        i64 c12,c22,c1c2;
        void init(){
            as[0]=1,bs[0]=1;
            for(int i=1;i<90;i++)cal(as[i-1],bs[i-1],as[i-1],bs[i-1],as[i],bs[i]);
            c12=i64(c1)*c1%P;
            c22=i64(c2)*c2%P;
            c1c2=i64(c1)*c2*2%P;
        }
        int operator[](i64 x){
            i64 v1,v2,v3;
            bool d=x&1;
            --x;
            int a=0,b=1;
            for(int i=0;x;i++,x>>=1)if(x&1)cal(a,b,as[i],bs[i],a,b);
            v1=a;v2=b;v3=a+b;
            if(d)return ((v1*v2+1)%P*c12%P+v2*v3%P*c22%P+v1*v3%P*c1c2%P)%P;
            return ((v1*v2+1)%P*c12%P+v2*v3%P*c22%P+v2*v2%P*c1c2%P)%P;
        }
    }a0;
    namespace Map{
        const int p=2939999;
        i64 xs[p];
        int ys[p];
        bool ed[p];
        int&get(i64 x){
            unsigned int w=x%p;
            while(ed[w]){
                if(xs[w]==x)return ys[w];
                w+=1237;
                if(w>=p)w-=p;
            }
            ed[w]=1;
            xs[w]=x;
            ys[w]=a0[x];
            if(ys[w]<0)ys[w]+=P;
            return ys[w];
        }
    }
    int stk[32],stp=0;
    int main(){
        i64 nth=1,ans=0;
        n=read();m=read();q=read();P=read();c1=read();c2=read();
        a0.init();
        for(int i=0;i<q;i++){
            i64 a=read64(),b=read64();
            int&a1=Map::get(a),&a2=Map::get(b),a3;
            a3=a1;a1=a2;a2=a3;
        }
        int xp=1,yp=1;
        ans=(ans+Map::get(1)*(nth++))%P;
        while(xp<n||yp<m){
            if(xp==n)++yp;
            else if(yp==m)++xp;
            else{
                int a1=Map::get(i64(xp)*m+yp),a2=Map::get(i64(xp-1)*m+yp+1);
                if(a1<a2)++xp;
                else ++yp;
            }
            ans=(ans+Map::get(i64(xp-1)*m+yp)*(nth++))%P;
        }
        printf("%lld
    ",(ans%P+P)%P);
        return 0;
    }
  • 相关阅读:
    【转】每天一个linux命令(41):ps命令
    【转】每天一个linux命令(40):wc命令
    【转】每天一个linux命令(39):grep 命令
    【转】每天一个linux命令(38):cal 命令
    【转】每天一个linux命令(37):date命令
    【转】每天一个linux命令(36):diff 命令
    【转】每天一个linux命令(35):ln 命令
    【转】每天一个linux命令(34):du 命令
    诗词、对联名句(千古名帖)
    诗词、对联名句(千古名帖)
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5354902.html
Copyright © 2011-2022 走看看