1 .51nod 1011
gcd,不解释
代码:
int gcd(a, b){
return b ? gcd(b, a%b) : a;
}
2 .51nod 1135
求最小原根
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define mem(a,b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
const int maxn = 1000005;
int yue[maxn], tot, cnt;
int v[maxn], prime[maxn];
void is_prime(){
mem(v,1);
for(int i = 2; i <= maxn; i++){
if(v[i]){
prime[++cnt] = i;
for(int j = i; j <= maxn; j += i){
v[j] = 0;
}
}
}
}
void div(int x){
tot = 0;
int t = (int)sqrt(1.0*x);
for(int i = 1; prime[i] <= t; i++){
if(x % prime[i] == 0){
yue[++tot] = prime[i];
while(x % prime[i] == 0) x /= prime[i];
}
}
if(x > 1)
yue[++tot] = x;
}
LL Pow(LL a, LL b, LL m){
LL ans = 1;
a %= m;
while(b){
if(b & 1)
ans = ans * a % m;
a = a * a % m;
b >>= 1;
}
return ans;
}
int main(){
int p;
is_prime();
while(scanf("%d", &p) == 1 && p){
div(p-1);
for(int i = 2; i <= p-1; i++){
bool flag = 1;
for(int j = 1; j <= tot; j++){
int t = (p-1)/yue[j];
if(Pow((LL)i, (LL)t, (LL)p) == 1){
flag = 0;
break;
}
}
if(flag){
printf("%d\n", i);
break;
}
}
}
return 0;
}
3 .51nod 1046
快速幂
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
LL Pow(LL a, LL b, LL p){
LL ans = 1LL;
a %= p;
while(b){
if(b & 1)
ans = ans * a % p;
a = a * a % p;
b >>= 1;
}
return ans;
}
int main(){
LL a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
printf("%lld\n", Pow(a, b, c));
return 0;
}
4. 51nod 1073
约瑟夫环
代码:
#include <iostream>
using namespace std;
int main(){
int n, k;
cin>>n>>k;
int s = 0;
for(int i = 1; i <= n; i++){
s = (s + k) % i;
}
cout<<s+1<<endl;
return 0;
}
5. 51nod 1256
乘法逆元(因为N不一定是素数,所以用exgcd求解)
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
void exgcd(LL a, LL b, LL &x, LL &y){
if(b == 0){
x = 1, y = 0;
return;
}
exgcd(b, a%b, x, y);
LL tmp = x;
x = y;
y = tmp - y * (a / b);
}
int main(){
LL a, b, x, y;
scanf("%lld%lld", &a, &b);
exgcd(a, b, x, y);
x = (x % b + b) % b;
printf("%lld\n",x);
return 0;
}
6. 51nod 1136
求欧拉函数值
代码:
#include <iostream>
#include <cmath>
using namespace std;
int phi(int n){
int ans = n;
for(int i = 2; i <= sqrt(n); i++){
if(n % i == 0){
ans = ans / i * (i-1);
while(n % i == 0) n /= i;
}
}
if(n > 1) ans = ans / n * (n-1);
return ans;
}
int main(){
int n;
cin>>n;
cout<<phi(n)<<endl;
return 0;
}
7 .51nod 1079
中国剩余定理
推荐博客:https://blog.csdn.net/acdreamers/article/details/8050018
https://www.cnblogs.com/MashiroSky/p/5918158.html
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
LL exgcd(LL a, LL b, LL &x, LL &y){
if(!b){
x = 1, y = 0;
return a;
}
int d = exgcd(b, a%b, x, y);
int tmp = x;
x = y;
y = tmp - (a/b)*y;
return d;
}
LL CSD(int m[], int a[], int n){
LL x = 0, y, d;
LL M = 1;
LL ans = 0;
for(int i = 1; i <= n; i++){
M *= m[i];
}
for(int i = 1; i <= n; i++){
LL Mi = M / m[i];
d = exgcd(Mi, m[i], x, y);
x = x/d;
ans = (ans + a[i]*Mi*x) % M;
}
return (ans + M) % M;
}
int main(){
int n, m[15], a[15];
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d %d", &m[i], &a[i]);
}
printf("%lld\n", CSD(m, a, n));
return 0;
}
8. 51nod 1240
莫比乌斯(mobius)函数
代码:
//求单个数的mobius值
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int c[1000005];
int main(){
int n, ans = 0, m = 0;
scanf("%d", &n);
int nn = n;
for(int i = 2; i <= sqrt(nn); i++){
if(n % i == 0){
c[++m] = 0;
while(n % i == 0){
n /= i;
c[m]++;
}
}
}
if(n > 1){
c[++m] = 1;
}
for(int i = 1; i <= m; i++){
if(c[i] >= 2){
printf("0\n");
return 0;
}
}
if(m & 1){
printf("-1\n");
}
else{
printf("1\n");
}
return 0;
}
//求2到n的mobius值
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int miu[1000005];
int v[1000005];
int n;
int main(){
scanf("%d", &n);
for(int i = 2; i <= n; i++) miu[i] = 1, v[i] = 0;
for(int i = 2; i <= n; i++){
if(v[i]) continue;
miu[i] = -1;
for(int j = 2*i; j <= n; j += i){
v[j] = 1;
if( (j / i) % i == 0 ) miu[j] = 0;
else miu[j] *= -1;
}
}
for(int i = 2; i <= n; i++){
printf("%d ", miu[i]);
}
return 0;
}
9. 51nod 1106
质数检测, 水题
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, t;
bool is_prime(int x){
for(int i = 2; i <= sqrt(x); i++){
if(x % i == 0){
return false;
}
}
return true;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &t);
if(is_prime(t))
printf("Yes\n");
else printf("No\n");
}
return 0;
}
10. 51nod 1012
lcm 算了还是不一个一个做了,这种水题。。。还是二分一下适合我的题。
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
LL gcd(LL a, LL b){
return b ? gcd(b, a%b) : a;
}
int main(){
LL a, b;
scanf("%lld %lld", &a, &b);
printf("%lld\n", a/gcd(a ,b)*b);
return 0;
}
11. 51nod 1186
Miller_Robbin 素性检测
为避免C++的高精度,用python编写
import random
def rand(l, r):
return int((r - l + 1) * random.random() + l)
def qpow(a, x, P):
ret = 1
while(x):
if(x & 1):
ret = ret * a % P
a = a * a % P
x >>= 1
return ret
def witness(a, n):
t = 0
u = n - 1;
while(not(u & 1)):
t += 1
u >>= 1
last = qpow(a, u, n)
for i in range(0, t):
cur = last * last % n
if(cur == 1 and last != 1 and last != n - 1):
return 1
last = cur
return (last != 1)
def miller_rabin(n, s):
if(n == 2):
return 1
for i in range(0, s):
a = rand(2, n - 1)
if witness(a, n):
return 0
return 1
n = int(input())
if(miller_rabin(n, 20)):
print("Yes")
else:
print("No")