#查找某篇题解:ctrl+f
#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 1181
题意:如果一个质数,在质数列表中的编号也是质数,那么就称之为质数中的质数。例如:3 5分别是排第2和第3的质数,所以他们是质数中的质数。现在给出一个数N,求>=N的最小的质数中的质数是多少?
题解:N范围是1e6,考虑用线性筛筛出1e7以下的素数,再把下标是素数的另存一个数组,二分查找答案即可。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn = (int)(1e7+100);
int p[maxn], v[maxn];
int pp[maxn];
int m, t;
void pre(){
memset(v, 0, sizeof(v));
for(int i = 2; i <= maxn; i++){
if(v[i] == 0){
v[i] = i;
p[++m] = i;
}
for(int j = 1; j <= m; j++){
if(v[i] < p[j] || p[j] > maxn/i) break;
v[i*p[j]] = p[j];
}
}
for(int i = 1; i <= m; i++){
if(v[i] == i){
pp[++t] = p[i];
//printf("%d ", i);
}
}
}
int main(){
pre();
int n;
scanf("%d", &n);
int x = lower_bound(pp+1, pp+t+1, n) - pp;
printf("%d\n", pp[x]);
return 0;
}
#12. 51nod 1080
题意:给出一个整数N,将N表示为2个整数i与j的平方之和(i <= j),如果有多种表示,按照i的递增序输出。
例如:N = 130,130 = 3^2 + 11^2 = 7^2 + 92(注:32 + 112同112 + 3^2算1种)
题解:i最大sqrt(n/2),暴力枚举即可。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
int v[40005];
int main(){
int n, t, flag = 1;
memset(v, 0, sizeof(v));
scanf("%d", &n);
t = (int)sqrt(n/2);
for(int i = 0; i <= t; i++){
int x = n - i*i;
int y = (int)sqrt(x);
if(y*y == x && !v[y]){
printf("%d %d\n", i, y);
v[i] = 1;
flag = 0;
}
}
if(flag){
printf("No Solution\n");
}
return 0;
}
#13. 51nod 1010
题意: K的因子中只包含2 3 5。满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15。
所有这样的K组成了一个序列S,现在给出一个数n,求S中 >= 给定数的最小的数。
例如:n = 13,S中 >= 13的最小的数是15,所以输出15。
题解: 预处理出1e18内的这样的数,二分查找即可。
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#define LL long long
using namespace std;
const LL maxn = (LL)1e18+100LL;
int T;
LL n;
LL num[1000005], tot;
void pre(){
tot = 0;
for(LL i = 1; i <= maxn; i *= 2LL){
for(LL j = 1; i*j <= maxn; j *= 3LL){
for(LL k = 1; i*j*k <= maxn; k *= 5LL){
if(i*j*k != 1)
num[++tot] = i*j*k;
}
}
}
sort(num+1, num+tot+1);
}
int main(){
pre();
scanf("%d", &T);
while(T--){
scanf("%lld", &n);
int x = lower_bound(num+1, num+1+tot, n) - num;
printf("%lld\n", num[x]);
}
return 0;
}
#14. 51nod 1126
**题意:**有一个序列是这样定义的:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
给出A,B和N,求f(n)的值。
题解::矩阵快速幂,转移矩阵为 [ 0 B 1 A ] \begin{bmatrix} 0&B\\1&A\\ \end{bmatrix} [01BA],不过要注意负数要加mod再mod。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int mod = 7;
int A, B, n;
void mul(int f[2], int a[2][2]){
int c[2];
memset(c, 0, sizeof(c));
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
c[i] = ( c[i] + (long long)f[j] * a[j][i] ) % mod;
}
}
memcpy(f, c, sizeof(c));
}
void mulself(int a[2][2]){
int c[2][2];
memset(c, 0, sizeof(c));
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
for(int k = 0; k < 2; k++){
c[i][j] = ( c[i][j] + (long long)a[i][k] * a[k][j] ) % mod;
}
}
}
memcpy(a, c, sizeof(c));
}
int main(){
scanf("%d%d%d",&A,&B,&n);
int f[2] = {1, 1};
int a[2][2];
a[0][0]= 0, a[1][0] = 1;
a[0][1] = B, a[1][1] = A;
n -= 1;
for(; n; n >>= 1){
if(n & 1) mul(f, a);
mulself(a);
}
printf("%d\n", (f[0]+mod) % mod);
return 0;
}
#15. 51nod 1014
题意: X*X mod P = A,其中P为质数。给出P和A,求<=P的所有X。
**题解:**枚举x即可。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define LL long long
int main(){
int p, a, flag = 0;
scanf("%d%d", &p, &a);
for(int i = 0; i <= p; i++){
LL x = (LL)i*i;
if(x % p == a){
printf("%d ", i);
flag = 1;
}
}
if(!flag)
printf("No Solution\n");
return 0;
}
#16. 51nod 1352
**题意:**给出N个固定集合{1,N},{2,N-1},{3,N-2},…,{N-1,2},{N,1}.求出有多少个集合满足:第一个元素是A的倍数且第二个元素是B的倍数。提示:对于第二组测试数据,集合分别是:{1,10},{2,9},{3,8},{4,7},{5,6},{6,5},{7,4},{8,3},{9,2},{10,1}.满足条件的是第2个和第8个。
题解:
1.设满足条件的是 ( t 1 , t 2 ) (t1, t2) (t1,t2), 即 ( A x , B y ) (Ax, By) (Ax,By),所以有 A x + B y = n + 1 Ax+By=n+1 Ax+By=n+1,转化为求这个方程的满足 1 < = A x < = n , 1 < = B y < = n 1<=Ax<=n, 1<=By<=n 1<=Ax<=n,1<=By<=n的解的个数。
2.先用扩展欧几里得求出 A x + B y = g c d ( A , B ) Ax+By=gcd(A, B) Ax+By=gcd(A,B)的一个解 x 0 x_0 x0,那么原方程的一个解就是 x 0 ∗ n + 1 d x_0*\frac {n+1}d x0∗dn+1.
3.公式变形: A x + B y = n + 1 Ax+By=n+1