SCUT - 485 - 质因数计数 - 原根
给定a和n,求有多少个质数p,满足n是使得a^n=1 mod p成立的最小正整数。
翻译:求有多少个质数p,使得a模p的阶delta_m(a)是n
先验证 a^n=1 mod p 成立
那么假如还有更小的m使得 a^m=1 mod p 成立,则这个p不合要求
由阶的性质有delta_m(a)|n,故只需要检查n的所有因子就可以了。
但其实不需要检查所有因子,只需要检查n的所有质因子。(从板子上面可以看出来,但是为什么)
即 a^(p_i) = 1 mod p 是否成立,假如恒不成立,则n是a模p的阶,其中p_i是n的每种质因子。
证明如下:很显然的,原本我们要检查n的所有因子才能确定阶,但是有一个更好的办法。
假如还有更小的m使得 a^m=1 mod p 成立,那么m的倍数km也一定满足 a^(km)=1 mod p 成立,那么从n中只去除一个质因子p_i,假如这个t=(n/p_i)有 a^t=1 mod p ,则可能存在更小的m使得 a^m=1 mod p 成立。否则假如 a^t != 1 mod p ,则t的所有因子也都不需要检查了。
这样就只需要检查log次。
1e9都直接暴力,快速幂还有个logn,真的服了没话讲。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int q, n;
const int MAXN = 1e7 + 5;
int p[MAXN], ptop;
int minp[MAXN];
bool np[MAXN];
void sieve(int n) {
np[1] = 1;
for(int i = 2; i <= n; i++) {
if(!np[i]) {
p[++ptop] = i;
minp[i] = i;
}
for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
minp[t] = p[j];
np[t] = 1;
if(i % p[j] == 0)
break;
}
}
}
int qpow(ll x, int n, int p) {
ll res = 1;
while(n) {
if(n & 1)
res = res * x % p;
x = x * x % p;
n >>= 1;
}
return res;
}
int ans[MAXN], atop;
int fac[60], ftop;
void GetFactor(int n) {
ftop = 0;
while(n != 1) {
int cp = minp[n];
fac[++ftop] = cp;
while(n % cp == 0)
n /= cp;
}
}
int check(int n, int P) {
if(qpow(q, n, P) != 1)
return 0;
for(int i = 1; i <= ftop; ++i) {
int t = n / fac[i];
if(qpow(q, t, P) == 1)
return 0;
}
return 1;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
sieve(MAXN);
while(~scanf("%d%d", &q, &n)) {
GetFactor(n);
atop = 0;
for(int i = 1; i <= ptop; ++i) {
if(check(n, p[i]))
ans[++atop] = p[i];
}
printf("%d\n", atop);
for(int i = 1; i <= atop; ++i)
printf("%d%c", ans[i], " \n"[i == atop]);
}
return 0;
}
直接上BSGS的话,假如这样的p有10000个就比较麻烦。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int q, n;
const int MAXN = 1e7 + 5;
int p[MAXN], ptop;
bool np[MAXN];
void sieve(int n) {
np[1] = 1;
for(int i = 2; i <= n; i++) {
if(!np[i])
p[++ptop] = i;
for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
np[t] = 1;
if(i % p[j] == 0)
break;
}
}
}
int qpow(ll x, int n, int p) {
ll res = 1;
while(n) {
if(n & 1)
res = res * x % p;
x = x * x % p;
n >>= 1;
}
return res;
}
unordered_map<int,int> M;
int bsgs(int a,int b,int n,int k=1,int t=0){
/*if(b==1)
return 0;*/
M.clear();
int m=ceil(sqrt(n));
ll s=b;
for(int i=0;i<m;++i,s=s*a%n){
M[s]=i;
}
s=k;
k=qpow(a,m,n);
for(ll i=1;i<=m;++i){
s=s*k%n;
if(M.count(s))
return i*m-M[s]+t;
}
return -1;
}
int ans[MAXN], atop;
int check(int n, int p) {
if(qpow(q, n, p) != 1)
return 0;
int res=bsgs(q,1,p);
if(res==-1||res==n)
return 1;
return 0;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
sieve(MAXN);
while(~scanf("%d%d", &q, &n)) {
atop = 0;
for(int i = 1; i <= ptop; ++i) {
if(check(n, p[i]))
ans[++atop] = p[i];
}
printf("%d\n", atop);
for(int i = 1; i <= atop; ++i)
printf("%d%c", ans[i], " \n"[i == atop]);
}
return 0;
}
SCUT - 485 - 质因数计数 - 原根的更多相关文章
- SCUT - 11 - 被钦定的选手 - 质因数分解
https://scut.online/p/11 T了好多次,还想用mutimap暴力分解每个数的质因数.后来记录每个数的最小质因子过了. #include <bits/stdc++.h> ...
- SCUT - 243 - 宝华复习 - 二分 - 桶计数
https://scut.online/p/243 这道题唯一难点在于如何快速确定m合法.可以统计滑动窗口中已有元素的数量. #include<bits/stdc++.h> using n ...
- 数论入门2——gcd,lcm,exGCD,欧拉定理,乘法逆元,(ex)CRT,(ex)BSGS,(ex)Lucas,原根,Miller-Rabin,Pollard-Rho
数论入门2 另一种类型的数论... GCD,LCM 定义\(gcd(a,b)\)为a和b的最大公约数,\(lcm(a,b)\)为a和b的最小公倍数,则有: 将a和b分解质因数为\(a=p1^{a1}p ...
- 【BZOJ】【1211】【HNOI2004】树的计数
Prufer序列+组合数学 嗯哼~给定每个点的度数!求树的种数!那么很自然的就想到是用prufer序列啦~(不知道prufer序列的……自己再找找资料吧,这里就不放了,可以去做一下BZOJ1005明明 ...
- 【poj1284-Primitive Roots】欧拉函数-奇素数的原根个数
http://poj.org/problem?id=1284 题意:给定一个奇素数p,求p的原根个数. 原根: { (xi mod p) | 1 <= i <= p-1 } is equa ...
- 原根求解算法 && NTT算法
原根求解算法: 获取一个数\(N\)的原根\(root\)的算法 #include<bits/stdc++.h> #define ll long long #define IL inlin ...
- 简单数论之整除&质因数分解&唯一分解定理
[整除] 若a被b整除,即a是b的倍数,那么记作b|a("|"是整除符号),读作"b整除a"或"a能被b整除".b叫做a的约数(或因数),a ...
- [总结]数论和组合计数类数学相关(定理&证明&板子)
0 写在前面 0.0 前言 由于我太菜了,导致一些东西一学就忘,特开此文来记录下最让我头痛的数学相关问题. 一些引用的文字都注释了原文链接,若侵犯了您的权益,敬请告知:若文章中出现错误,也烦请告知. ...
- BZOJ2219数论之神——BSGS+中国剩余定理+原根与指标+欧拉定理+exgcd
题目描述 在ACM_DIY群中,有一位叫做“傻崽”的同学由于在数论方面造诣很高,被称为数轮之神!对于任何数论问题,他都能瞬间秒杀!一天他在群里面问了一个神题: 对于给定的3个非负整数 A,B,K 求出 ...
随机推荐
- end of sleepyhead
- java 上传大文件以及文件夹
我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...
- CDOJ 1060 秋实大哥与快餐店 字典树 水题
题目链接 B - 秋实大哥与快餐店 Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%lld & %llu Sub ...
- 使用WebStorm运行vue项目
在WebStorm中怎么打开一个已有的项目,这个不用多说,那么如何运行一个vue项目呢? 1.点击下图中右上角的红框. 2.在出现的弹框中选中左上角“+”下的“npm”,如下图所示. 3.选中第二步的 ...
- 管理es索引-使用 Xput创建索引
curl是利用URL语法在命令行方式下工作的开源文件传输工具,使用curl可以简单实现常见的get/post请求.简单的认为是可以在命令行下面访问url的一个工具.在centos的默认库里面是有cur ...
- sqli-lab(37)
0X01 看看源码 what is mean? 定义和用法 mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符. 下列字符受影响: \x00 \n ...
- HTTP请求方式之POST和GET的区别
GET请求方式: 如果我们的网页收集到的用户数据,他规定了,此网页用户数据用GET的请求方式去处理的话,我们会发现,比如百度,就是一个很经典的GET请求方式 当我们在百度搜索上输入一个‘java’,点 ...
- 将Windows下的文件同步到Linux下
需求:把Windows下的某些文件自动传送到Linux指定目录下 实现: 1. Windows下安装 WinSCP工具,并把Liunx服务器信息保存 2. 编写脚本,实现双击工具就把Windows下的 ...
- nginx利用try_files实现多个源
比如一个视频网站,视频资源分散在几台机器上,但是给用要提供统一的IP,路径,端口.就需要nginx,先检查本机是否有改文件,如果没有就代理其他地方 location / { root /data/ww ...
- ros the public key is not available
W: An error occurred during the signature verification. The repository is not updated and the previo ...