zoukankan      html  css  js  c++  java
  • 【zoj3254】Secret Code

    题意:

    给出a、p、d、m 求a^x=d(mod p) 0<=x<=m 的解的个数

    题解:

    今天一整天的时间大部分都在调这题Orz BSGS什么的还是太不熟了

    我们可以用BSGS拓展版求出最小解x 以及循环节开始的位置start start就是p被除(a,p)的次数

    如果不存在解x 或x>m则输出0

    如果x<start 那么输出1 因为如果解在循环节之前 在循环节中就不可能有x的解

    如果start<=x<=m 答案就是x循环出现的次数=(m-x)/lon (lon是循环节长度)

    这有些地方要注意的

    因为题目的m<=2^63-1 而0<=x<=m 所以可能导致答案爆long long 要开unsigned long long

    还有该mod的地方要mod啊 因为一个mod 我段异常了一个早上

    然后因为对BSGS不熟 WA了一下午TAT 按AK大神的打法重打一遍才过

    代码:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 typedef long long ll;
      5 typedef unsigned long long ull;
      6 const ll mo=200003,N=20000;
      7 ll a,p,d,m,sum=1,sq,hash[mo],hat[mo],pri[N],save[N],bo[N+1],tot,add;
      8 ll gcd(ll a,ll b){ return b ? gcd(b,a%b) : a; }
      9 ll extgcd(ll &x,ll &y,ll a,ll b){
     10     if (!b){
     11         x=1,y=0;
     12         return a;
     13     }else{
     14         ll res=extgcd(x,y,b,a%b),t=x;
     15         x=y,y=t-a/b*y;
     16         return res;
     17     }
     18 }
     19 void push(ll x,ll y){
     20     ll t=x%mo;
     21     while (hash[t]>=0){
     22         if (hash[t]==x) return;
     23         t=(t+1)%mo;
     24     }
     25     hash[t]=x,hat[t]=y;
     26 }
     27 void makehash(){
     28     for (ll i=0,x=1%p;i<sq;i++,x=x*a%p) push(x,i);
     29 }
     30 ll ha(ll x){
     31     ll t=x%mo;
     32     while (hash[t]>=0){
     33         if (hash[t]==x) return hat[t];
     34         t=(t+1)%mo;
     35     }
     36     return -1;
     37 }
     38 ll mi(ll a,ll b){
     39     ll res=1;
     40     for (;b;b>>=1){
     41         if (b&1) res=res*a%p;
     42         a=a*a%p;
     43     }
     44     return res;
     45 }
     46 ll makex(){
     47     ll x,y,a1,b1=p,res;
     48     for (ll i=0;i<=sq;i++){
     49         a1=mi(a,sq*i)*sum%p;
     50         ll gc=extgcd(x,y,a1,b1),xx=b1/gc;
     51         if (d%gc) continue;
     52         x=(d/gc*x%xx+xx)%xx;
     53         res=ha(x);
     54         if (res>=0 && res<=p)
     55         return i*sq+res+add;
     56     }
     57     return -1;
     58 }
     59 void makepri(){
     60     for (ll i=2;i<=N;i++){
     61         if (!bo[i]) pri[++pri[0]]=i;
     62         for (ll j=1;j<=pri[0] && i*pri[j]<=N;j++){
     63             bo[i*pri[j]]=1;
     64             if (!(i%pri[j])) break;
     65         }
     66     }
     67 }
     68 bool check(ll t){ return mi(a,t)==1; }
     69 void makesave(ll x){
     70     save[0]=0;
     71     for (ll i=1;i<=pri[0] && x>1;++i)
     72     if (!(x%pri[i])){
     73         save[++save[0]]=pri[i];
     74         while (!(x%pri[i])) x/=pri[i];
     75     }
     76     if (x>1) save[++save[0]]=x;
     77 }
     78 ll phi(ll t){
     79     makesave(t);
     80     ll res=t;
     81     for (ll i=1;i<=save[0];i++)
     82     res=res/save[i]*(save[i]-1);
     83     return res;
     84 }
     85 ll makelon(){
     86     ll t=phi(p);
     87     makesave(t);
     88     for (ll i=1;i<=save[0];i++)
     89     while (check(t/save[i]) && !(t%save[i])) t/=save[i];
     90     return t;
     91 }
     92 int bsgs(){
     93     int addx=1,sd=d,sp=p;
     94     for (int gc=gcd(a,p);gc>1;gc=gcd(a,p)){
     95         if (addx==sd) return add++;
     96         if (d%gc) return -1;
     97         addx=addx*a%sp;
     98         d/=gc,p/=gc;
     99         sum=a/gc*sum%p;
    100         ++add;
    101     }
    102     sq=(ll)sqrt(p);
    103     a%=p;
    104     makehash();
    105     return makex();
    106 }
    107 void work(){
    108     ull res=0;
    109     add=0,sum=1;
    110     memset(hash,-1,sizeof(hash));
    111     ll x=bsgs();
    112     if (x==-1 || x>m){
    113         puts("0");
    114         return ;
    115     }else if (x<add){
    116         puts("1");
    117         return;
    118     }
    119     ll lon=makelon();
    120     res=(m-x)/lon+1;
    121     printf("%I64u
    ",res);
    122 } 
    123 int main(){
    124     makepri();
    125     while (scanf("%I64d%I64d%I64d%I64d",&a,&p,&d,&m)!=EOF){
    126         ++tot;
    127         //printf("%d:",tot);
    128         a%=p;
    129         work();
    130     }
    131 }
    View Code

  • 相关阅读:
    saltstack安装和配置
    puppet安装和配置
    mongodb使用
    mongdb安装
    redis数据类型
    redis安装
    memcached结合php以及memcache共享session
    yum安装的Apache的各种配置文件的位置
    memcached 基本操作
    memcached基本操作和语法
  • 原文地址:https://www.cnblogs.com/g-word/p/3376980.html
Copyright © 2011-2022 走看看