学习了元根的一些知识,哈哈。

总结一下:

几个概念:

阶:对于模数m和整数a,并且gcd(m,a)==1,那么定义a在模m下的阶r为满足ar=1 mod m的最小正整数。

性质1:r in [1,phi(m)]   (由欧拉定理)

性质2:r | phi(m)  ( ar=aphi(m) mod m,然后用反证法)

性质3:r 是整数a模m的阶当且仅当满足:1)ar=1 mod m   2) a r/p(r) ≠ 1 mod m (后面推前面也用反正法)。

元根:

如果对于一个模数m,存在一个数a,满足a在模m下的阶是phi(m),那么就称a是模数m的一个元根。

性质:所有质数有元根(更一般的,2,4,pe,2pe有元根,p是奇质数)

元根应用

元根依靠离散对数,将对数运算引入了模数的缩系下。从而可以解决很多数论中关于指数的问题。

indga=indgb mod phi(m) <=> a=b mod m

indgak=k indga mod phi(m)

indgab=indga+indgb mod phi(m)

 #include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std; typedef long long dnt; const int mod = ;
const int elen = ;
struct Hash {
int head[mod], val[elen], rat[elen], next[elen], etot;
void init() {
memset( head, , sizeof(head) );
etot = ;
}
void insert( int v, int r ) {
int k = v % mod;
etot++;
next[etot] = head[k];
rat[etot] = r;
val[etot] = v;
head[k] = etot;
}
int query( int v ) {
int k = v % mod;
for( int t=head[k]; t; t=next[t] )
if( val[t]==v ) return rat[t];
return -;
}
}hash; int p, a, k;
int g, b;
vector<int> stk; dnt mpow( dnt a, int b, int m ) {
dnt rt;
for( rt=; b; b>>=,a=(a*a)%m )
if( b& ) rt=(rt*a)%m;
return rt;
}
void exgcd( int a, int b, int &d, dnt &x, dnt &y ) {
if( b== ) d=a, x=, y=;
else {
exgcd( b, a%b, d, y, x );
y-=a/b*x;
}
}
int gcd( int a, int b ) {
return b ? gcd(b,a%b) : a;
}
int findroot( int n ) { // n is prime
if( n== ) return ; vector<int> pfac;
int maxi = (int)ceil(sqrt(n-));
int remain=n-;
for( int i=; i<=maxi; i++ ) {
if( remain%i== ) {
pfac.push_back(i);
while( remain%i== )
remain/=i;
}
}
if( remain!= ) pfac.push_back( remain );
for( int i=; ; i++ ) {
bool ok = true;
for( int t=; t<pfac.size(); t++ )
if( mpow(i,(n-)/pfac[t],n)== ) {
ok = false;
break;
}
if( ok ) return i;
}
}
dnt inv( int a, int n ) {
return mpow(a,n-,n);
}
dnt ind( int g, int b, int n ) { // n is prime, g is root, return v in [0,n-1]
hash.init();
int m = (int)ceil(sqrt(n-));
dnt s = ;
for( int i=; i<m; i++ ) {
if( s==b ) return i;
hash.insert( s, i );
s = (s*g) % n;
}
int am = s;
s = b;
for( int i=m,j; i<n; i+=m ) {
s = (s*inv(am,n)) % n;
if( (j=hash.query(s))!=- )
return i+j;
}
return -; // impossible
}
void meq( int a, int b, int m ) {
stk.clear();
int d = gcd(a,m);
if( b%d ) return;
int aa=a/d, bb=b/d, mm=m/d, dd;
dnt x0, y0;
exgcd( aa, mm, dd, x0, y0 );
x0 = (x0%mm+mm)%mm;
for( dnt k=; k<d; k++ )
stk.push_back( (x0*bb+k*mm)%m );
} int main() {
scanf( "%d%d%d", &p, &k, &a ); // x^k = a mod p
if( a== ) {
printf( "1\n0 \n" );
return ;
}
// find the root of p: g
g = findroot(p);
// ind a: b
b = ind( g, a, p );
// kx=b mod phi(p)
meq( k, b, p- );
// decode
for( int t=; t<stk.size(); t++ )
stk[t] = mpow( g, stk[t], p );
sort( stk.begin(), stk.end() );
// output
printf( "%d\n", stk.size() );
for( int t=; t<stk.size(); t++ )
printf( "%d ", stk[t] );
printf( "\n" );
}

sgu 261的更多相关文章

  1. SGU 261. Discrete Roots (N次剩余)

    N次剩余 题目:http://acm.sgu.ru/problem.php? contest=0&problem=261 题意:给定n,a,p 求出x^n ≡ a(mod p)在模p意义下的全 ...

  2. SGU 261. Discrete Roots

    给定\(p, k, A\),满足\(k, p\)是质数,求 \[x^k \equiv A \mod p\] 不会... upd:3:29 两边取指标,是求 \[k\text{ind}_x\equiv ...

  3. 一些数论概念与算法——从SGU261谈起

    话说好久没来博客上面写过东西了,之前集训过于辛苦了,但有很大的收获,我觉得有必要把它们拿出来总结分享.之前一直是个数论渣(小学初中没好好念过竞赛的缘故吧),经过一道题目对一些基础算法有了比较深刻的理解 ...

  4. java.lang.IllegalArgumentException: Illegal character in query at index 261

    在BaseFragment中使用了LoadingPage,而LoadingPage的联网加载使用的是AsyncHttpClient.一直报java.lang.IllegalArgumentExcept ...

  5. Codeforces #261 D

    Codeforces #261 D D. Pashmak and Parmida's problem time limit per test 3 seconds memory limit per te ...

  6. SGU 495. Kids and Prizes

    水概率....SGU里难得的水题.... 495. Kids and Prizes Time limit per test: 0.5 second(s)Memory limit: 262144 kil ...

  7. ACM: SGU 101 Domino- 欧拉回路-并查集

    sgu 101 - Domino Time Limit:250MS     Memory Limit:4096KB     64bit IO Format:%I64d & %I64u Desc ...

  8. 【SGU】495. Kids and Prizes

    http://acm.sgu.ru/problem.php?contest=0&problem=495 题意:N个箱子M个人,初始N个箱子都有一个礼物,M个人依次等概率取一个箱子,如果有礼物则 ...

  9. SGU 455 Sequence analysis(Cycle detection,floyd判圈算法)

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=455 Due to the slow 'mod' and 'div' operati ...

随机推荐

  1. 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器

    刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

  2. angular select ng-change实时获取value

    <select ng-model="vm.selectVal" ng-options="o.id as o.title for o in vm.optionsDat ...

  3. spring boot 测试用例

    junit 是一个面向于研发人员使用的轻量的测试模块,适合做单元测试.而testng百度后发现更强大,可以做功能测试,但对于我这种RD,貌似junit足沟了呢! java Mock PowerMock ...

  4. android入门问题--R文件丢失

    链接   新手刚入门as,发现新创建的项目总是出错 Error:Execution failed for task ':app:mergeDebugResources'. > Error: ja ...

  5. luoguP2735 电网 Electric Fences

    一道校内模拟赛遇见的题 ** 不会正解就真的很麻烦的 数学题 ** 有一种东西叫 皮克定理 发现的千古神犇: 姓名:George Alexander Pick(所以叫皮克定理呀 国籍:奥地利(蛤!竟然 ...

  6. wpf 查找 子元素

    RightContainer.ApplyTemplate();//如果找不到,就执行该句试一试 var xxx=UIHelper.FindChild<ScrollViewer>(Right ...

  7. Linux学习笔记:vi常用命令

    在Linux系统中常用vi命令进行文本编辑. vi命令是UNIX操作系统和类UNIX操作系统中最通用的全屏幕纯文本编辑器.Linux中的vi编辑器叫vim,它是vi的增强版(vi Improved), ...

  8. 【剑指Offer面试题】 九度OJ1389:变态跳楼梯

    转自:http://www.myexception.cn/program/1973966.html 时间限制:1 秒内存限制:32 兆特殊判题:否提交:2331解决:1332 题目描述: 一只青蛙一次 ...

  9. DDD领域模型企业级系统(一)

    领域模型的基本构造块: 1.实体(Entity):有业务生命周期,使用标识进行跟踪. 2.值对象(Value Object):无业务生命周期,用来描述实体. 3.服务(Service):无状态的行为类 ...

  10. Activity总结练习

    package com.example.wang.myapplication; import android.content.Intent; import android.os.Bundle; imp ...