若m=0,

就是求n^2n ≡ x mod p (x--)

因为一定优解,所以x一定是p的二次剩余

令g为p的1个原根,且g^k ≡ x mod p

则k是偶数,证明k是偶数:

假设

g1^k1 ≡ x mod p

g2^k2 ≡ x mod p,k2是偶数

g1^k3 ≡ g2 mod p

那么 g1^k3k2 ≡ x ≡ g1^k1 mod p

由欧拉定理可得,k3k2 ≡ k1 mod p-1

∴ k1是偶数

所以对于任意g,k是偶数

所以等价于求 n^n ≡ g^(k/2) mod p

显然

满足 n≡ g mod  p  且  n ≡ k/2 mod p-1 的n 是一个可行解

又因为p与p-1一定互质,所以用CRT即可求得n

若m≠0

求n^2n+n^m ≡ x mod p

在上面m=0 的时候,我们是令 n ≡ g mod p

即 n^m ≡ g^m mod p

能解出合法的n的条件是 x-n^m 是p的二次剩余

所以尝试枚举g,判断x-g^m 是否是p的二次剩余

判断方法:利用欧拉准则计算勒让德符号,即 判断(x-n^m)^ ((p-1)/2)  mod p 是否等于1

如果x-g^m 是 p的二次剩余

方程变成 n^2n ≡ x-g^m mod p

令g^k ≡ x-g^m mod p

用BSGS求出一个满足上述条件的k

若k是偶数

那么方程就变成了 n^n ≡ g^(k/2) mod p

满足 n≡ g mod  p  且  n ≡ k/2 mod p-1 的n 是一个可行解

又因为p与p-1一定互质,所以用CRT即可求得n

#include<map>
#include<cmath>
#include<cstdio>
#include<iostream> using namespace std; map<int,int>mp; int Pow(int a,int b,int p)
{
int res=1;
for(;b;a=1LL*a*a%p,b>>=1)
if(b&1) res=1LL*res*a%p;
return res;
} long long Mul(long long a,int b,long long p)
{
long long res=0;
while(b)
{
if(b&1) res+=a,res%=p;
b>>=1; a+=a; a%=p;
}
return res;
} bool Legendre(int n,int p)
{
return Pow(n,p-1>>1,p)+1!=p;
} int bsgs(int a,int b,int p)
{
mp.clear();
int m=sqrt(p);
mp[b]=0;
for(int i=1;i<=m;++i)
{
b=1LL*a*b%p;
mp[b]=i;
}
int am=Pow(a,m,p);
int mul=1;
for(int i=1;i<=m;++i)
{
mul=1LL*mul*am%p;
if(mp.find(mul)!=mp.end()) return i*m-mp[mul];
}
return -1;
} int inv(int a,int p)
{
return Pow(a,p-2,p);
} int main()
{
freopen("theory.in","r",stdin);
freopen("theory.out","w",stdout);
int x,m,p;
scanf("%d%d%d",&x,&m,&p);
if(p==2) printf("1");
int y;
long long ans;
for(int g=1;;++g)
{
if(!Legendre(x-Pow(g,m,p),p)) continue;
y=bsgs(g,(x-Pow(g,m,p)+p)%p,p);
if(y==-1 || (y&1)) continue;
long long P=1LL*p*(p-1);
ans=Mul(1LL*(p-1)*inv(p-1,p)%P,g,P)+1LL*p*(y/2)%P;
ans%=P;
cout<<ans;
return 0;
}
}

  

 
 

cdqz2017-test1-数论 (BSGS + 二次剩余 + CRT)的更多相关文章

  1. 【模板】【数论】二次剩余Cipolla算法,离散对数BSGS 算法

    Cipolla LL ksm(LL k,LL n) { LL s=1; for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo; return s; } n ...

  2. BZOJ 2219 数论之神 (CRT推论+BSGS+原根指标)

    看了Po神的题解一下子就懂了A了! 不过Po神的代码出锅了-solve中"d-temp"并没有什么用QwQQwQQwQ-应该把模数除以p^temp次方才行. 来自BZOJ讨论板的h ...

  3. bzoj5104 Fib数列(BSGS+二次剩余)

    快AFO了才第一次写二次剩余的题…… 显然应该将Fn写成通项公式(具体是什么写起来不方便而且大家也都知道),设t=((1+√5)/2)n,T=√5N,然后可以得到t-(-1)t/t=√5N,两边同时乘 ...

  4. luogu 2480 古代猪文 数论合集(CRT+Lucas+qpow+逆元)

    一句话题意:G 的 sigma d|n  C(n d) 次幂  mod 999911659 (我好辣鸡呀还是不会mathjax) 分析: 1.利用欧拉定理简化模运算 ,将上方幂设为x,则x=原式mod ...

  5. 【bzoj3122】: [Sdoi2013]随机数生成器 数论-BSGS

    [bzoj3122]: [Sdoi2013]随机数生成器 当a>=2 化简得 然后 BSGS 求解 其他的特判 : 当 x=t  n=1 当 a=1  当 a=0 判断b==t /* http: ...

  6. JZOJ 5796 划分 (容斥,数论,扩展CRT)

    题面 有一个未知的序列 x,长度为 n.它的 K-划分序列 y 指的是每连续 K 个数的和得到划 分序列,y[1]=x[1]+x[2]+....+x[K],y[2]=x[K+1]+x[K+2]+... ...

  7. ACM模板_axiomofchoice

    目录 语法 c++ java 动态规划 多重背包 最长不下降子序列 计算几何 向量(结构体) 平面集合基本操作 二维凸包 旋转卡壳 最大空矩形 | 扫描法 平面最近点对 | 分治 最小圆覆盖 | 随机 ...

  8. 板子-GOD BLESS ALL OF YOU

    字符串: KMP #include<cstdio> #include<cstring> ; ]; ]; int l1,l2; void get_next() { next[]= ...

  9. Cipolla算法学习小记

    转自:http://blog.csdn.net/doyouseeman/article/details/52033204 简介 Cipolla算法是解决二次剩余强有力的工具,一个脑洞大开的算法. 认真 ...

随机推荐

  1. AtCoder 瞎做

    目录 ARC 058 E - 和風いろはちゃん / Iroha and Haiku 题意 题解 技巧 代码 ARC 059 F - バイナリハック / Unhappy Hacking 题意 题解 技巧 ...

  2. IT项目管理——《人月神话》读后感

    这也许是和候红老师的最后的几节课了吧,侯老师是一个很有思想深度,很关心同学的好老师. 一开学就布置了阅读<人月神话>的作业,说实话,我没有看,以我的速度可能2.3个小时就看完了,但是我觉得 ...

  3. hdu 1686 Oulipo (kmp)

    Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, w ...

  4. 用python批量向数据库(MySQL)中导入数据

    用python批量向数据库(MySQL)中导入数据 现有数十万条数据,如下的经过打乱处理过的数据进行导入 数据库内部的表格的数据格式如下与下面的表格结构相同 Current database: pyt ...

  5. 洛谷P3265 装备购买

    这个大毒瘤题....居然反向卡精度.... 别的题eps要开小,这个毒瘤要开大... 我一开始是1e-12,挂的奇惨无比,50分...... 然后改成1e-7,就70分了... 1e-5 90分 1e ...

  6. codevs1260 快餐问题

    题意: 一个套餐需要a个A,b个B,c个C. 你生产一个A需要t1,一个B需要t2,一个C需要t3时间. 你有n台机器.每台每天工作timei时间. 一件物品只能在一个机器上生产. 求你一天最多能生产 ...

  7. HDU3032 Nim or not Nim?

    解:使用sg函数打表发现规律,然后暴力异或起来即可. #include <bits/stdc++.h> typedef long long LL; ; int a[N]; inline L ...

  8. Linux基本命令总结(二)

    接上篇: 7,cp命令用来复制文件或者目录,是Linux系统中最常用的命令之一.一般情况下,shell会设置一个别名,在命令行下复制文件时,如果目标文件已经存在,就会询问是否覆盖,不管你是否使用-i参 ...

  9. luogu4211 LCA

    题目链接 思路 我们换一种求\(dep[lca(i,j)]\)的方法. 将从根到\(i\)的路径上所有点的权值加\(1\),然后求从根节点到j路径上点的权值和.就是\(i\)和\(j\)的\(lca\ ...

  10. (转)c++ 回调函数

    https://www.cnblogs.com/chenyuming507950417/archive/2012/01/02/2310114.html 今天讨论下C/C++中的回调函数. 在理解“回调 ...