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

[SDOI2013]随机数生成器

时间:2018-10-04 10:39:03      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:main   随机数   lse   mem   note   ace   while   .so   数学   

https://www.zybuluo.com/ysner/note/1300007

题面

都过来看题解了,应该知道题面是什么吧

解析

好像还是\(BSGS\)模板题。
虽然说我不看标签还不一定能意识到要用bsgs

看到递推式之类的,应该要想到矩乘或者某些数学理论。。。
题目的问题矩乘处理不了。
也只能\(BSGS\)

设第\(n\)天读到第\(t\)页。
想想怎么把未知数弄到指数那里去。
数学必修五中常常给出递推式,要我们证一个玩意儿是等比数列。
这里要反其道而行。
\[x_{i+1}=ax_i+b\]
解下方程发现其等比数列形式是:
\[x_{i+1}+\frac{b}{a-1}=a(x_i+\frac{b}{a-1})\]
那么\[x_n+\frac{b}{a-1}=a^{n-1}(x_1+\frac{b}{a-1})\]
咦,\(t\)是指数!
\[a^{t-1}\equiv\frac{x_n+\frac{b}{a-1}}{x_1+\frac{b}{a-1}}\pmod p\]
其中\(x_n=t\)
然后套上\(BSGS\)模板就可以了。

显然\(a=0,a=1\)的时候需要特判。
我在特判上栽了两次。。。

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define re register
#define il inline
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=5e4,mod=45807;
int T;
int p,a,b,s,t,z,y;
il int gi()
{
  re int x=0,t=1;
  re char ch=getchar();
  while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
  if(ch==‘-‘) t=-1,ch=getchar();
  while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-48,ch=getchar();
  return x*t;
}
il ll ksm(re ll S,re ll n)
{
  re ll T=S;S=1;
  while(n)
    {
      if(n&1) S=S*T%p;
      T=T*T%p;
      n>>=1;
    }
  return S;
}
struct Hash_table
{
  struct Edge{int u,v,nxt;}e[N*10];
  int h[N],cnt;
  il void clear(){memset(h,-1,sizeof(h));cnt=0;}
  il void add(re int u,re int v,re int w){e[++cnt]=(Edge){w,v,h[u]};h[u]=cnt;}
  il int Query(re int x)
  {
    for(re int i=h[x%mod];i+1;i=e[i].nxt)
    if(e[i].u==x) return e[i].v;
    return -1;
  }
  il void solve(re int y,re int z)
  {
    y%=p;z%=p;
    if(!y||!z) {puts("-1");return;}
    re int m=sqrt(p)+1;clear();
    for(re int i=0,t=z;i<m;++i,t=1ll*t*y%p) add(t%mod,i,t);
    for(re int i=1,tt=ksm(y,m),t=tt;i<=m;++i,t=1ll*tt*t%p)
      {
    re int j=Query(t);if(j==-1) continue;
        printf("%d\n",i*m-j+1);return;
      }
    puts("-1");
  }
}BSGS;
int main()
{
  T=gi();
  while(T--)
    {
      p=gi();a=gi();b=gi();s=gi();t=gi();
      if(s==t) {puts("1");continue;}
      if(a==0)
    {
      if(b==t) puts("2");else puts("-1");//if(b==t) puts("1");????
      continue;
    }
      if(a==1)
    {
      if(b==0) puts("-1");
      else
        {
          re ll gu=1ll*(t+p-s)%p*ksm(b,p-2)%p;
          printf("%lld\n",gu+1);//printf("%lld\n",gu);????
        }
      continue;
    }
      re ll gu=1ll*b*ksm(a-1,p-2)%p;
      y=a;z=1ll*(t+gu)%p*ksm(s+gu,p-2)%p;
      BSGS.solve(y,z);
    }  
  return 0;
}

[SDOI2013]随机数生成器

标签:main   随机数   lse   mem   note   ace   while   .so   数学   

原文地址:https://www.cnblogs.com/yanshannan/p/9739821.html

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