JZOJ 4015 数列

题面:

SOL:

前7个点: 暴力。

8到 14个点: 我们发现m很小,记 f(x)=ax^2+bx+c,那么对于每一个x,f(x)唯一确定,那么这个数列的周期很小,上界是O(m),我们把循环节算出来%一%就好了。

15到 20 个点 : 记b=2a*t, 那么 xn=a(xn-1+t)^2-t, xn+t=a(xn-1+t)^t

 所以  xn+t=a^(2^n-1)*xo^(2^n), 又因为m为质数,那么 x^p=x^(p%(m-1)) (mod m)

#include<bits/stdc++.h>
#define LL long long
using namespace std;
#define N 1000007
LL x0,a,b,c,n,m,siz,pp;
int aa[N],p[N];
LL qsm(LL x,LL m,LL y){
    static LL anw;
    for (anw=1;y;y>>=1,x=x*x%m) 
     if (y&1) anw=anw*x%m;
    return anw;
}
signed main () {
    scanf("%lld%lld%lld%lld%lld%lld"
    ,&x0,&a,&b,&c,&n,&m);
    x0%=m;
    if (n<1000000) {
        while (n--) {
            x0=a*x0%m*x0%m+b*x0%m+c;
            x0%=m;
        }
        printf("%lld\n",x0); return 0;
    }
    if (m<=1000000) {
        for (int i=1;i<=m+10;i++) {
            x0=a*x0%m*x0%m+b*x0%m+c;
            x0%=m; aa[i]=x0;
            if (i==n) {
                printf("%lld\n",x0); return 0;
            }
            if (p[x0]) {
                int len=i-p[x0]; n-=i; n%=len;
                printf("%d\n",aa[p[x0]+n]); return 0;
            } else p[x0]=i;
        }
    }
    x0+=b*qsm(2*a%m,m,m-2)%m;  
    siz=qsm(2,m-1,n); pp=siz?siz-1:m-2;
    printf("%lld\n",(m+qsm(x0,m,siz)*qsm(a,m,pp)%m-b*qsm(2*a%m,m,m-2)%m)%m);
    return 0;
}

 

posted @ 2018-07-13 14:45  泪寒之雪  阅读(183)  评论(0编辑  收藏  举报