码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ4471 : 随机数生成器Ⅱ

时间:2016-04-04 19:31:57      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

\[\begin{eqnarray*}
x_i&=&x_{i-1}+x_{i-2}\\
x_i^2&=&x_{i-2}^2+x_{i-1}^2+2x_{i-2}x_{i-1}\\
x_{i-1}x_i&=&(x_{i-3}+x_{i-2})(x_{i-2}+x_{i-1})\\
&=&2x_{i-3}x_{i-2}+x_{i-2}x_{i-1}+x_{i-3}^2+x_{i-2}^2
\end{eqnarray*}\]

故可以构造转移矩阵$A$进行递推。

不妨设$n\geq m$,则可以预处理出$A^0,A^1,...,A^n$以及$A^n,A^{2n},...,A^{nn}$。

那么查询某个数的复杂度为$8^3$。

总时间复杂度为$O(n(8^3+\log n))$。

 

#include<cstdio>
#include<algorithm>
#include<map>
#define rep(i) for(int i=0;i<8;i++)
using namespace std;
typedef long long ll;
const int N=8,M=100005;
int n,m,lim,q,P,C1,C2,i,j,x,y;map<ll,int>T;
inline void read(ll&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
struct mat{
  int a[N][N];
  mat(){rep(i)rep(j)a[i][j]=0;}
  mat operator*(const mat&b){
    mat c;
    rep(i)rep(k)if(a[i][k])rep(j)if(b.a[k][j])c.a[i][j]=(1LL*a[i][k]*b.a[k][j]+c.a[i][j])%P;
    return c;
  }
}A[M],pA[M],B;
inline int get(ll t){
  t--;
  mat C=pA[t/lim]*A[t%lim]*B;
  return C.a[7][0];
}
inline int ask(int x,int y){
  if(x>n||y>m)return P;
  ll t=1LL*(x-1)*m+y;
  if(T.find(t)!=T.end())return T[t];
  return get(t);
}
int main(){
  rep(i)A[0].a[i][i]=1;
  A[1].a[0][1]=1;
  A[1].a[1][0]=A[1].a[1][1]=1;
  A[1].a[2][3]=1;
  A[1].a[3][4]=1;
  A[1].a[4][3]=A[1].a[4][4]=1,A[1].a[4][6]=2;
  A[1].a[5][6]=1;
  A[1].a[6][2]=A[1].a[6][3]=A[1].a[6][6]=1,A[1].a[6][5]=2;
  A[1].a[7][4]=A[1].a[7][7]=1;
  scanf("%d%d%d%d%d%d",&n,&m,&q,&P,&C1,&C2);
  B.a[0][0]=C2;
  B.a[1][0]=(C1+C2)%P;
  B.a[2][0]=1LL*C1*C1%P;
  B.a[3][0]=1LL*C2*C2%P;
  B.a[4][0]=1LL*(C1+C2)*(C1+C2)%P;
  B.a[5][0]=1LL*C1*C2%P;
  B.a[6][0]=1LL*C2*(C1+C2)%P;
  B.a[7][0]=(1LL*C1*C1+1LL*C2*C2)%P;
  lim=n>m?n:m;
  for(i=2;i<=lim;i++)A[i]=A[i-1]*A[1];
  for(pA[0]=A[0],i=1;i<=lim;i++)pA[i]=pA[i-1]*A[lim];
  for(i=1;i<=q;i++){
    ll x,y;
    read(x),read(y);
    if(T.find(x)==T.end())T[x]=get(x);
    if(T.find(y)==T.end())T[y]=get(y);
    swap(T[x],T[y]);
  }
  for(i=x=y=1;i<n+m-1;i++){
    printf("%d ",ask(x,y));
    if(ask(x+1,y)<=ask(x,y+1))x++;else y++;
  }
  return printf("%d",ask(n,m)),0;
}

  

BZOJ4471 : 随机数生成器Ⅱ

标签:

原文地址:http://www.cnblogs.com/clrs97/p/5352447.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!