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; }