知识补充:裴蜀定理

1.Bi-shoe and Phi-shoe

1.题意

给出一行数,求对应的数的欧拉函数值大于给出的数的数的最小和。

2.思路

我们知道素数表的欧拉函数值递增。
设素数a,b,b是a的下一个素数,则phi[a]<ph[b],且a-b间的所有数的欧拉函数都小于等于phi[a]。
欧拉函数值大于x的数的最小的数就是大于x的最小的素数

3.代码
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int N = 1001005;
int prime[N],cnt;
bool st[N];
int c=1;
void Prime(int n){st[0] = st[1] = 1;for(int i = 2; i <= n; ++i){if(!st[i]) prime[cnt++]=i;for(int j = 0; prime[j]<= n/i; ++j){st[i*prime[j]] = 1;if(i%prime[j]==0) break;}}
}
int main(){int t;cin >> t;Prime(N);while(t--){int n;cin >> n;LL ans=0;for(int i = 0; i < n; ++i){int x;cin >> x;for(int j = x+1; ;++j){if(!st[j]) { //如果是素数ans+=j;break;}}}printf("Case %d: %lld Xukha\n",cnt++,ans);}return 0;
}

2.Prime Independence

1.题意
2.思路
3.代码

3.Aladdin and the Flying Carpet

1.题意

给出整数 a 和 b ,求区间[b, a] 内的 a 的约数对的个数,即:满足c*d == a 且 c>=b,d>=b。a 的约数对(比如[2, 5] 与 [5, 2] 为同一对)。

2.思路

线性筛+唯一分解定理
根据唯一分解定理,先将a唯一分解,则a的所有正约数的个数为num = (1 + a1) * (1 + a2) *…(1 + ai),这里的ai是素因子的指数,见唯一分解定理,因为题目说了不会存在c==d的情况,因此num要除2,去掉重复情况,然后枚举小于b的a的约数,拿num减掉就可以了。

3.代码
#include"bits/stdc++.h"
#define s(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sl2(a,b) scanf("%lld%lld",&a,&b)
using namespace std;
typedef long long ll;
const int MAXN = 1000010;
int prime[MAXN];
bool vis[MAXN];
int t;
int cnt=1;
int num=0;
void Prime(int n){memset(vis,0,sizeof(vis));vis[0] = vis[1] = 1;for(int i = 2; i <= n; ++i){if(!vis[i]) prime[cnt++] = i;for(int j = 1; j <= cnt && i*prime[j]<=n ; ++j){vis[i*prime[j]] = 1; //prime[j]是素数,他的倍数也是素数 if( i%prime[j] == 0) break; //i是某个素数的倍数,直接跳出 }}
}
ll getfac(ll x)
{ll ans=1;for(int i=1;prime[i]<=x/prime[j];i++){ll sum=0;//当前质因数的幂指数while(x%prime[i]==0)//当是这个数的因子时{sum++;x/=prime[i];}ans*=(sum+1);//应用定理的结论}if(x>1)//当搜索不到的时候,如果这个数最后大于一,那么这个最后结果肯定是素数,并且指数是1ans*=2;return ans;
}int main(){Prime(MAXN);s(t);while(t--) {ll a, b;scanf("%lld%lld",&a,&b);if(a<b*b) {printf("Case %d: 0\n",++num);continue;}ll ans = getfac(a)/2;for(ll i = 1; i < b; ++i)if(a%i==0) ans--;printf("Case %d: %lld\n",++num,ans);}return 0;
}

4.Sigma Function

1.题意

求从1-n的数中约数和是偶数的数的个数

2.思路

1-100打表
不满足的数/和
1 1
2 3
4 7
8 15
9 13
16 31
18 39
25 31
32 63
36 91
49 57
50 93
64 127
72 195
81 121
98 171
100 217

发现100中,因子和为奇数的有:

1 2 4 6 9 16 18 25 32 36 49 50 64 72 81 98 100

有没有发现,这些数字有一个规律,他们是 x^2, 2x, 2x^2, 只要100中的数满足这三个中的一个,那么,这个数就是不满足的,

总数-不满足的个数 = 满足的个数

我们还可以发现:
当x为偶数时2x和x^2会有重复的部分
当x为奇数时2
x和2*x^2会有重复的部分
最后发现x^2和 2x^2涵盖了所有情况,且不重复,因此减去这两中情况的数目即可

3.代码
#include "bits/stdc++.h"
#define s(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define s2(a,b) scanf("%d%d",&a,&b)
#define sl2(a,b) scnaf("%lld%lld",&a,&b)
using namespace std;
typedef long long ll;
int cnt=1;
int main(){int t;cin>>t;while(t--){ll n;cin>>n;ll ans=0;ll x = sqrt(n);ll y = sqrt(1.0*n/2);ans=n-x-y;printf("Case %d: %lld\n",cnt++, ans);}return 0;
}

5.Leading and Trailing

1.题意

求n^k前三位和后三位

2.思路

1.暴力跑肯定超时
2.后三位好求,n^k%1000即可
前三位需要变形:参考大佬的推导

接下来我们求k+lgn即可
怎么求呢,有个函数学习一下modf()

求出小数部分b后,计算一下就好啦,不过要注意最后要输出3位,需要控制一下输出格式,当n^k=10000000时,对1000取余结果为0,需要再补2个0

3.代码
    #include "bits/stdc++.h"#define s(a) scanf("%d",&a)#define sl(a) scanf("%lld",&a)#define s2(a,b) scanf("%d%d",&a,&b)#define sl2(a,b) scanf("%lld%lld",&a,&b)using namespace std;typedef long long ll;int t, cnt=1;double x,y;ll n,k;ll quick_mod(ll a,ll b,ll p){ll num=a,sum=1;while(b){if(b&1) sum=sum*num%p;num=num*num%p;b>>=1;}return sum;}///a^b mod p*/int main(){//freopen("d://data.txt" ,"w" ,stdout);cin>>t;while(t--){cin>>n>>k;y = modf((double)(k*log10(n)),&x);ll ans1 = pow(10,y)*100;ll ans2=quick_mod(n,k,1000);printf("Case %d: %03lld %03lld\n",cnt++, ans1,ans2);}return 0;}
//注意输出格式,后三位可能存在最大位为十位或个位,需要补0

6.Goldbach`s Conjecture

1.题意

求n=a+b且a,b都是素数这样的a,b的对数

2.思路

素数筛模板题
遍历素数表prime[i],若n-prime[i]也是素数,ans++
prime[i]>n/2时结束,因为后面再跑就重复了嘛

3.代码
#include "bits/stdc++.h"#define s(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define s2(a, b) scanf("%d%d",&a,&b)
#define sl2(a, b) scanf("%lld%lld",&a,&b)
using namespace std;
typedef long long ll;
int t, c = 1;
const int MAXN = 1e7+10;
int prime[1000000];
bool vis[MAXN];
int cnt = 0;
void Prime(int n) {memset(vis, 0, sizeof(vis));vis[0] = vis[1] = 1;for (int i = 2; i <= n; ++i) {if (!vis[i]) prime[cnt++] = i;for (int j = 0; j < cnt && i * prime[j] <= n; ++j) {vis[i * prime[j]] = 1; //prime[j]是素数,他的倍数也是素数if (i % prime[j] == 0) break; //i是某个素数的倍数,直接跳出}}
}int main() {//freopen("d://data.txt" ,"w" ,stdout);Prime(MAXN);cin >> t;while (t--) {int n,ans=0;cin >> n;for(int i =0; i < cnt; ++i){if(prime[i]>n/2) break;if(!vis[n-prime[i]]) ans++;}printf("Case %d: %d\n",c++, ans);}return 0;
}

7.Harmonic Number (II)

1.题意

求n*(1+1/2+1/3+…+1/n)

2.思路

分块数论

3.代码
#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
int t,cnt= 1;
int main(){scanf("%d",&t);while(t--){ll n,sum = 0;scanf("%lld",&n);for(ll l=1,r;l<=n; l=r+1){r = n/(n/l);sum+=n/l*(r-l+1);}printf("Case %d: %lld\n",cnt++,sum);}return 0;
}
//对称点(sqrt(n),sqrt(n)),求一半面积乘2//分块数论:https://blog.csdn.net/weixin_43627118/article/details/104024380?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

8.Pairs Forming LCM

1.题意

在a,b中(a,b<=n),有多少组(a,b) (a<b)满足lcm(a,b)==n;

2.思路

素因子分解:n = p1 ^ e1 * p2 ^ e2 *…*pn ^ en
取n的两个因子a,b
a=p1 ^ a1 * p2 ^ a2 *…*pn ^ an
b=p1 ^ b1 * p2 ^ b2 *…*pn ^ bn

**gcd(a,b)=p1 ^ min(a1,b1) * p2 ^ min(a2,b2) *…*pn ^ min(an,bn)
lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) pn ^ max(an,bn)

分解n,n = p1 ^ e1 * p2 ^ e2 *…*pk ^ ek,

lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) *…*pk ^ max(ak,bk)

所以,当lcm(a,b)==n时,max(a1,b1)==e1,max(a2,b2)==e2,…max(ak,bk)==ek

当ai == ei时,bi可取 [0, ei] 中的所有数 有 ei+1 种情况,bi==ei时同理。

那么就有2(ei+1)种取法,但是当ai = bi = ei 时有重复,所以取法数为2(ei+1)-1=2ei+1。
除了 (n, n) 所有的情况都出现了两次 那么满足a<=b的有 (2
ei + 1)) / 2 + 1 个,+1的情况是a = b的时候
参考dl

3.代码
#include <bits/stdc++.h>
using namespace std;
int k;
long long suv[100500];
const int N=10000100;
long long prime[N/10]={0};
int num_prime=0;
bool isNotPrime[N]={1,1};
void su(){for(long i = 2 ; i < N ; i ++){if(!isNotPrime[i])prime[num_prime++]=i;for(long j = 0 ; j < num_prime &&i*prime[j]<N ;j ++) {isNotPrime[i * prime[j]] = 1;if( !(i % prime[j]))break;}}
}
void prime_solve(long long n){memset(suv,0,sizeof(suv));for(long long i=0;i<num_prime&&prime[i]*prime[i]<=n;i++){//        cout<<prime[i]<<endl;if(n%prime[i]==0){while(n%prime[i]==0){n/=prime[i];suv[k]++;}//cout<<prime[i]<<" "<<suv[k]<<endl;k++;}}if(n!=1)suv[k++]=1;
}//用这种分解方法比较快int main(){int t;scanf("%d",&t);int m=1;su();while(t--){long long n;scanf("%lld",&n);k=0;prime_solve(n);long long sum=1;for(int i=0;i<k;i++)sum*=(2*suv[i]+1);printf("Case %d: %lld\n",m++,(sum+1)/2);}return 0;
}
//https://blog.csdn.net/acvay/article/details/47333871

9.Harmonic Number

1.题意

输入n,求调和级数

2.思路

结论题。
当n很小的时候,前缀和预处理,O(1)访问
当n很大的时候,调和级数的近似和为:f(n)=ln(n)+C+1/(2*n);
C为欧拉常数
C = 0.57721566490153286060651209

3.代码
#include"iostream"
#include"cmath"
#include"cstdio"
using namespace std;
const int N = 100005;
const double r = 0.57721566490153286060651209;//欧拉常数
double a[N];
int main(){for(int i = 1; i <= N; ++i)a[i] = a[i-1] + 1.0/i;int t, cnt = 0;cin >> t;while(t--){int n;cin >> n;if(n <= N) printf("Case %d: %.10f\n",++cnt, a[n]);else printf("Case %d: %.10f\n",++cnt, log(n) + r + 1.0/(2*n));}return 0;
}

10.Mysterious Bacteria

1.题意

x=b^p 给出x求出最小的p

2.思路

开始想两层循环暴力跑,底数从1~2^16(65536),幂从1到32,后来发现不对,大于1e7的样例就跑不出来了。

后来又想用唯一分解定理写,以为要求最大的pi,发现还是不对
补充知识:任何一个数都可以分解成如下形式:x = p1x1*p2x2*p3x3*…*psxs,pi为质数

比如:24 = 2^3 * 3^1
但这里答案并不是3,因为题目要求最后的底数就一个b,所以需要能合并。
再如:324 = 3^4 * 2^2,发现p应该是gcd(4, 2) = 2,即324 = 18^2
因此得出p=gcd(x1,x2,x3,x4…,xk)

还有一个坑点就是n可以是负数,此时需要转化为正数来求。

如果p是偶数,需要做修正,因为-16 != -2^4,所以,需要除2使其变成奇数,比如-324 = -(18^2) = -324^1
如果p是奇数,一个数的奇数次幂可以是负数,则不需要调整。

参考网友

3.代码

错误代码

#include"iostream"
#include"cmath"
#include"cstdio"
using namespace std;
typedef long long LL;
const int N = 65536;
int main(){int t, cnt = 0;cin >> t;while(t--){LL n;cin >> n;bool f = 0;for(int i = 1; i <= N; ++i){LL p = 1;for(int j = 1; j <= 32; ++j){p*=i;if( p == n) {printf("Case %d: %d\n",++cnt, j);f = 1;break;}}if(f) break;}}return 0;
}

AC代码

#include"iostream"
#include"cmath"
#include"cstdio"
using namespace std;
typedef long long LL;
const int N = 1e5+10;
int prime[N],cnt;
bool st[N];
LL gcd(LL a, LL b)
{return b ? gcd(b, a % b) : a;
}
void Prime(int n){ //线性筛for(int i = 2; i <= n; ++i){if(!st[i]) prime[ cnt ++] = i;for(int j = 0; prime[j] <= n/i; ++j){st[prime[j] * i] = 1;if(i % prime[j] == 0) break;}}
}
int main(){Prime(N);int t, c = 0;cin >> t;while(t--){LL n;bool f= 0;  //标记n的正负cin >> n;if(n < 0) n = -n, f = 1;  //n是负数,标记一下,后面做修正int p = 0;for(LL i = 0; prime[i] <= n/prime[i]; ++i){ //素数分解定理if(n % prime[i] ==0){LL s = 0;while(n %prime[i] == 0){n/=prime[i];s++;}if(p == 0) p = s;else p = gcd(p, s);}}if(n > 1) p = gcd(p, 1);if(f)  while( p%2 == 0) p >>= 1;  //如果n是负数,那么p只能是奇数,因为一个数的偶次幂必然是正数,所以作除2操作将其变成奇数printf("Case %d: %lld\n",++c, p);}return 0;
}

11.Large Division

1.题意

大数取余

2.思路

大数除法模板题

3.代码
#include"iostream"
#include"cmath"
#include"cstdio"
#include"unordered_map"
#include"vector"
using namespace std;
typedef long long LL;
// A / b = C ... r, A >= 0, b > 0
int main(){int t, c = 0;scanf("%d",&t);while(t--){string a;LL b,r;cin >> a >> b;if(b < 0) b = -b;vector<int>A;for(int i = a.size()-1; i >=0 ; --i) if(a[i] == '-') continue;else A.push_back(a[i]-'0');vector<int> C;int r = 0;for (int i = A.size() - 1; i >= 0; i -- ){r = r * 10 + A[i];C.push_back(r / b);r %= b;}if(r == 0)printf("Case %d: divisible\n",++c);elseprintf("Case %d: not divisible\n",++c);}return 0;
}

Python直接写

# Python代码
t = int(input())
c = 1
while t:if t == 0:breaka, b = map(int, input().split())if a % b == 0:print("Case " + str(c) + ": divisible")else:print(print("Case " + str(c) + ": not divisible"))t = t - 1c = c + 1

12.Fantasy of a Summation

1.题意

优化题目中的代码,题目中复杂度为n^k

2.思路

找规律,写几组样例即可发现一共有kn^k个数,而且每个数出现的次数是一样的,那么每个数出现的次数就是kn ^(k-1),那么答案:ans =∑(i从1到n) a[i] * k * n ^(k-1) = sum * k * n ^(k-1); 用快速幂求即可。

3.代码
#include"iostream"
using namespace std;
typedef long long LL;
int cnt = 0;
LL qp(LL a, LL b, LL p){LL res = 1;while(b){if( b&1 ) res = res * a %p;b>>=1;a = a * a % p;}return res;
}
int main(){int t;cin >> t;while(t--){LL n, k, p;scanf("%lld%lld%lld", &n, &k, &p);LL sum = 0;for(int i = 1; i <= n; ++i){LL x; scanf("%lld",&x);sum += x;sum %= p;}sum = (sum * k) % p * qp(n,k-1, p) % p;printf("Case %d: %lld\n",++cnt,sum);}return 0;
}

13.Help Hanzo

1.题意

求a到b的素数的个数

2.思路

二次筛法

这里的区间范围给定的最大值是2^31 - 1,而用线性筛法求的是[1,n]中的所有质数,因此直接用线性筛法求肯定会直接gg,因此需要通过挖掘某些性质,才能有技巧性的完成。


参考来源

注意点:
1.筛[a,b]之间的素数时,要从第一个大于a并且是素数倍数的数开始,当a,b比较小的时候,可能[a,b]中包含素数p,因此:max((a+p-1)/p * p, 2*p)
2.需要注意偏移量,因为b-a<=1e5,那么s标记数st开到1e5就可以(我们这里开到1e6是因为要筛出2^16以内的素数),如果不做偏移量修正,那么可能需要访问到st[1e9],显然数组开不到这么大。

3.代码
#include "iostream"
#include "cmath"
#include "cstring"
using namespace std;
typedef long long LL;
const int N = 1000010;
int c = 0;
int prime[N],cnt;
bool st[N];void Prime(int n){memset(st, 0 ,sizeof st);cnt = 0;for(int i = 2; i<= n; ++i){if(!st[i]) prime[cnt ++] = i;for(int j = 0; prime[j] <= n/i; ++j){st[prime[j] * i] = 1;if( i % prime[j] == 0) break;}}
}
int main(){Prime(N);int t;scanf("%d",&t);while(t--){memset(st, 0, sizeof st);LL a,b;scanf("%lld%lld", &a, &b);for(int i = 0; i < cnt; ++i){int p = prime[i];//筛去[a,b]的合数for(LL j = max((a+p-1)/p*p, 2ll*p); j <= b; j+=p) st[j - a] = 1;}cnt = 0;for(int i = 0; i <= b-a; ++i)if(i+a > 1 && !st[i]) ++cnt;printf("Case %d: %d\n", ++c, cnt);}return 0;
}

14.Trailing Zeroes (III)

1.题意

输入q,代表N!末尾有q个0,求出最小的N

2.思路

打表到20!发现:
0-4:末尾无0
5-9:末尾1个0
10-14:末尾2个0
15-19:末尾3个0

猜测N每+5,末尾就多1个0
但是这样显然求不到q = 1e8时的N

重新思考:
N!末尾的0一定是由2*5产生的。
而且2因子的个数一定比5因子的个数多。
所以只需要求N!的5因子的个数。
用到了一个数论知识:
若p是质数,p<=n,则n!是p的倍数,设p^x是p在n!内的最高幂,则
x=[n/p]+[n/p^2]+ [n/p^3]+…;
而且[n/(ab)]=[[n/a]/b]
参考来源

3.代码
#include"iostream"
using namespace std;
int c;
const int N = 5e8;
int find(int x){int sum = 0;while(x){sum += x/5;x/=5; } return sum;
}
int check(int x){int l=1,r=N;while(l <= r){int mid = (l+r) >>1;int t = find(mid);if(t < x) l = mid + 1;else if(t > x) r = mid - 1;else return mid; }return -1;
}
int main(){int t;scanf("%d", &t);while(t--){int x;scanf("%d", &x);printf("Case %d: ",++c);int p = check(x);if(p==-1) puts("impossible");else printf("%d\n",p-p%5); //求出最小的满足条件的N,比如这里q=1时,求出的答案是7,需要ans-ans%5 }     return 0;
}

15.GCD - Extreme (II)

1.题意

找出一个数的阶乘的末尾0个数是q

2.思路
3.代码

16.Code Feat

1.题意
2.思路
3.代码

17.Emoogle Grid

1.题意
2.思路
3.代码

18.青蛙的约会

1.题意

青蛙A,B在一条环形线上,抽象成数轴,长度为l,起始坐标分别为x、y,单位跳跃距离分别为n,m,问最少走几次l能相遇,若不能相遇输出impossible

2.思路

参考来源

3.代码
#include<cstdio>
#define LL long long
LL x,y,m,n,l,a,b,c,x0,y0,g,tmp;
void exgcd(LL a,LL b){if(!b){x0=1;g=a;return;}//顺便求gcdexgcd(b,a%b);tmp=x0;x0=y0;y0=tmp-a/b*y0;
}
int main(){scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);a=n-m;b=l;c=x-y;if(a<0)a=-a,c=-c;//处理a为负数情况exgcd(a,b);if(c%g)puts("Impossible");else printf("%lld\n",(c/g*x0%(b/g)+b/g)%(b/g));//求最小非负整数解return 0;
}

19.C Looooops

1.题意

求a+bx≡c(mod 2^k)

2.思路

题目的意思就是 a+bx≡c(mod 2^k)
典型的线性同余方程 转化为 bx-y2^k=c-a 当gcd(b,2^k)能整除c-a的时候 就存在解
通解好求 跑一边exgcd可以得出x0 然后 基础解 x=(c-a)/gcd(b,2^k)x0; 通解为 x0+zz(2^ k/gcd(2^k,b); 显然当zz=0的时候最小
关键是要求出最小正整数解。
对于ax+by=gcd(a,b) 这个方程 我们有通解 x=x0+b/gcd(a,b);
那么怎么求x的最小正整数解。呢 首先知道一点 b/gcd(a,b)是解的最小区间
这个怎么理解呢
假设c为x的解的最小间距,此时d为y的解的间距,所以x=x0+ct,y=y0-d*t(x0,y0为一组特解,t为任意整数)

  带入方程得:a*x0+a*c*t+b*y0-b*d*t=n,因为a*x0+b*y0=n,所以a*c*t-b*d*t=0,t不等于0时,a*c=b*d因为a,b,c,d都为正整数,所以用最小的c,d,使得等式成立,ac,bd就应该等于a,b的最小公倍数a*b/gcd(a,b),所以c=b/gcd(a,b),d就等于a/gcd(a,b)。

所以,若最后所求解要求x为最小整数,那么x=(x0%(b/gcd(a,b))+b/gcd(a,b))%(b/gcd(a,b))即为x的最小整数解。

x0%(b/gcd(a,b))使解落到区间-b/gcd(a,b) ~ b/gcd(a,b),再加上b/gcd(a,b)使解在区间0~2*b/gcd(a,b),

再模上b/gcd(a,b),则得到最小整数解
参考链接

3.代码
#include "iostream"
#include "cstdio"
using namespace std;
typedef long long LL;
LL a,b,c,k;LL exgcd(LL a,LL b, LL &x,LL &y){if(!b){x = 1,y = 0;return a;}LL d = exgcd(b, a%b, y, x);y -= a/b*x;return d;
}
int main(){while(scanf("%lld%lld%lld%lld",&a,&b,&c,&k),a+b+c+k){LL x,y;LL p = b-a;LL z = 1ll << k;LL d = exgcd(c,z,x,y);if(p%d) puts("FOREVER");else{LL t = z/d;x = (x*(p/d)%t+t)%t;printf("%lld\n",x);}}return 0;
}

20.Death to Binary?

1.题意
2.思路
3.代码

21.Primes

1.题意

1-16000,是素数输出yes,否则no

2.思路

素数筛筛一遍1-16000
注意1,2要输出no,n<=则结束输出

3.代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 20010;
int c=0;
int prime[N],cnt;
bool st[N];
void Prime(int n){st[1] = 1;for(int i = 2; i <= n; ++i){if(!st[i]) prime[cnt ++] = i;for(int j = 0; prime[j] <= n/i;++j){st[prime[j] * i] = 1;if( i % prime[j] ==0) break;}}st[2]=1;
}
int main()
{Prime(N);int n;while(cin >> n&&n>0) {printf("%d: ",++c);if(st[n]) puts("no");else puts("yes");}return 0;
}

22.Maximum GCD

1.题意

n个数中选2个,求gcd,找出最大的gcd

2.思路

暴力跑
输入很花哨,用getline

3.代码
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int n,num,a[110];
string s;
int gcd(int a,int b)
{return b?gcd(b, a%b):a;
}
int main()
{cin>>n;getchar();while(n--){num=0;getline(cin,s);stringstream ss(s);while(ss>>a[num]) num++; //控制读入int ans=0;for(int i=0;i<num;i++)for(int j=i+1;j<num;j++)ans=max(ans,gcd(a[i],a[j]));cout<<ans<<endl;}return 0;
}

23.Prime Time

1.题意

对于fn = n^2+ n + 41,n属于[l,r],求素数的概率

2.思路

跑一下就可
这题结果要加1e-8
前缀和打表,否则超时

3.代码
#include "iostream"
#include "cstdio"
using namespace std;
const int N = 100010;
int sum[N];
bool isPrime(int n){for(int i = 2; i <= n/i; ++i)if(n%i==0) return 0;return 1;
}
void init(){int num;for(int  i = 0; i < N; ++i){int f = i*i+i+41;if(isPrime(f)) num++;sum[i] = num;}
}
int main(){int l,r;double ans;init();while(~scanf("%d%d",&l,&r)){if(l==0) ans = 100.00*sum[r]/(r-l+1);else ans = 100.00*(sum[r]-sum[l-1])/(r-l+1);printf("%.2f\n",(double)ans+1e-8);}return 0;
}

24.The equation

1.题意

线性方程区间求解的个数

2.思路

参考

3.代码
#include"bits/stdc++.h"
using namespace std;
typedef long long LL:
LL a,b,c,x1,x2,y1,y2,x,y;
inline long long cmin(const long long &x,const long long &y) {return x<y?x:y;}
inline long long cmax(const long long &x,const long long &y) {return x>y?x:y;}
void exgcd(LL a,LL b)
{if (!b){x = 1;y = 0;return;}LL d = exgcd(b, a%b, y, x);y -= a/b*x;return d;
}
int main()
{cin >> a >> b >> c >> x1 >> x2 >> y1 >> y2;c=-c;if (c<0) {a = -a, b =- b, c =- c;if (a<0) {a =- a; LL t = x1;x1 = -x2; x2 = -t;}if (b<0) {b = -b;LL t = y1; y1 = -y2; y2 = -t;}if (a == 0 && b == 0){if (c == 0){cout << (x2-x1+1)*(y2-y1+1) <<endl;return 0;}else cout <<0<<endl; return 0;}else if (a == 0){if (c%b == 0)if (c/b<=y2 && c/b>=yy1)  cout << x2-x1+1 <<endl;else cout << 0 << endl;return 0;}else if (b == 0){if (c%a == 0)if (c/a <= x2 && c/a >= x1) cout << y2-y1+1 << endl;else printf("0");return 0;}long long d=gcd(a,b);if (c%d!=0){printf("0");return 0;}a=a/d;b=b/d;c=c/d;exgcd(a,b);x0=x0*c;yy0=yy0*c;double tx2=x2,tx1=x1,tx0=x0,ta=a,tb=b,tc=c,ty1=yy1,ty2=y2,ty0=yy0;long long down1=floor(((tx2-tx0)/tb)),down2=floor(((ty0-ty1)/ta));long long r=cmin(down1,down2);long long up1=ceil(((tx1-tx0)/tb)),up2=ceil(((ty0-ty2)/ta));long long l=cmax(up1,up2);if (r<l) printf("0");else printf("%I64d",r-l+1);return 0;}

25.Farey Sequence

1.题意

欧拉函数模板题

2.思路

素数筛+欧拉函数+前缀和

3.代码
#include "iostream"
using namespace std;
typedef long long LL;
const int N = 1e6+10;
int prime[N],cnt;
LL phi[N];
bool st[N];
void eluer(int n){phi[1] = 1;for(int i = 2; i <= n; ++i){if(!st[i])  {prime[cnt ++] = i;phi[i] = i-1;}for(int j = 0; prime[j] <= n/i; ++j){st[prime[j] * i] = 1;if(i % prime[j] == 0) {phi[prime[j] * i] = prime[j]*phi[i];break;}else phi[prime[j] * i] = (prime[j]-1)*phi[i];}}
}
int main(){int n;eluer(N);for(int i = 3; i <= N; ++i) phi[i]+=phi[i-1];while(cin>>n,n){cout << phi[n] << endl;}return 0;
}

26.The Super Powers

1.题意

输出所有可以表示成a^b 或者(a^ b)^c的数
比如:
16 = 2^4= 4^2
64 = 8^2 = 2^6

2.思路

最大到2^64-1暴力找肯定超时

可以想到, 如果a^b可以拆分, 那么b一定是个合数
如此看来幂的范围是:[4 - 64)
底数范围:[2, 2^16)
a的最大次幂:b = loga(2^64-1) = log(2^64-1) / log(i);
求的过程中会有重复的,用set存即可去重

3.代码
#include "iostream"
#include "set"
#include "cmath"
using namespace std;
typedef unsigned long long LL;
const int N = 1<<16;
set<LL>se;
const int index[50] =
{4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26,27, 28, 30, 32, 33, 34, 35, 36, 38, 39, 40, 42, 44, 45, 46,48, 49, 50, 51, 52, 54, 55, 56, 57, 58, 60, 62, 63, 64  /// 多算一个
};///合数表
int main(){se.insert(1);LL x=1;for(int i = 2; i < N; ++i){x=(LL)i*i;x*=x;se.insert(x);int t = ceil(64 * log(2) / log(i)) - 1;for(int j = 1; index[j] <= t; ++j){x*=(index[j]-index[j-1]==2)?i*i:i;se.insert(x);}}for(auto s : se)cout << s<<endl;return 0;
}

【ACM】kuangbin基础数论专题相关推荐

  1. ACM数论专题3——素数(质数)

    ACM数论专题3--素数 素数是什么 蛮力算法求素数 蛮力算法的实现以及分析 时间复杂度 蛮力算法的改进 时间复杂度 **埃筛** 时间复杂度 线筛 线筛原理分析 线筛实现 素数是什么 质数1 (pr ...

  2. 数学/数论专题-学习笔记:狄利克雷卷积

    数学/数论专题-学习笔记:狄利克雷卷积 1. 前言 2. 一些基础函数 3. 积性函数 4. 狄利克雷卷积 5. 总结 6. 参考资料 1. 前言 狄利克雷卷积,是学习与继续探究 μ\muμ 函数和 ...

  3. 数论专题(一)数论基本概念

    努力努力再努力x 努力努力再努力x 博客园 首页 新随笔 联系 订阅 管理 数论专题(一)数论基本概念 转载自:https://blog.csdn.net/whereisherofrom/articl ...

  4. 数学/数论专题:莫比乌斯函数与欧拉函数

    数学/数论专题:莫比乌斯函数与欧拉函数(进阶) 0. 前言 1. 前置知识 2. 正文 3. 总结 4. 参考资料 0. 前言 本篇文章会从狄利克雷卷积的角度,讨论莫比乌斯函数与欧拉函数的相关性质. ...

  5. 算法之基础数论应用篇(一)

    基础数论应用篇 子集和 题目描述 筛质数 筛质数模板 欧拉筛 线性筛 哥德巴赫猜想 夏洛克和他的女朋友 二次筛法 分解质因数 试除法分解质因数 分解阶乘质因子 快速幂 模板 快速幂 快速乘法 序列的第 ...

  6. nssl1174-阶乘【!基础!数论】

    前言 比赛时xjq说这道题很水,是个基础数论. 然后- 就连交都没交 正题 给出n个数,求一个最小的mmm使得 m!∏i=1nai=q(q∈N+)\frac{m!}{\prod_{i=1}^na_i} ...

  7. 计算机内存知识txt,计算机内存基础知识专题

    计算机内存基础知识专题 计算机是由哪几部分组成的呢?简单的说,一个完整的计算机系统是由软件和硬件组成的.其中,硬件部分由中央处理单元(运算器和控制器).存储器和输入/输出设备构成.这次我们要谈的是存储 ...

  8. 数学/基础数论——从LeetCode题海中总结常见套路

    今天是大年初一,祝大家新年快乐! 目录 基础数论求质数:LeetCode204.计数质数 常规解法: 娱乐一下:偷鸡式解法 埃拉托色尼筛选法 统计5因子的个数:LeetCode172.阶乘后的零 暴力 ...

  9. 【数论】基础数论概念

    基础数论概念 首先我们来回顾一下基础数论中关于整数集Z={-,-2,-1,0,1,2,-}和自然数集N={0,1,2,3,4,-}的一些概念. 整除性与约数 一个整数可以被另一个整数整除是数论中的一个 ...

最新文章

  1. YoloV5代码详细解读
  2. 改进 网站资源探测工具(添加代理)
  3. webService学习3:客户端生成webservice代码
  4. 微信小程序小结(3) -- 使用wxParse解析html及多数据循环
  5. 固执己见的框架(例如Spring Boot)的危险。 求知代码反转
  6. PHPCMS 模板的设置
  7. 今日头条ocpm计费规则_入门篇|信息流广告的游戏规则—竞价机制
  8. Android第四十五天
  9. 蟒蛇语言和python_蛇、蟒、蚺、蝰有什么区别
  10. win2003server域控服务器安装及设置
  11. trunk端口_超全!华为交换机端口vlan详解~
  12. 【转】TCP状态变迁图
  13. protocal buffer repeate 关键字
  14. PIPIOJ1099PIPI的油田
  15. Arduino + SmartAirFilter 制作智能感应的 PM 空气净化器
  16. PRML读书会第一章 Introduction(机器学习基本概念、学习理论、模型选择、维灾等)...
  17. 分级阅读网站/阅读网站.阅读系统的设计与实现
  18. 过敏体质也会遗传给孩子,孕期妈妈应该尽早预防
  19. 计算机音乐锦鲤抄,锦鲤抄 MIDI File Download :: MidiShow
  20. Django计算机毕业设计JAVA高校田径运动会管理python(源码程序+lw+远程部署)

热门文章

  1. npm install --save-dev
  2. echarts 饼图的图例的颜色和图例的颜色相同的设置
  3. 在微信小游戏中开发一个贪食蛇
  4. 关于移动硬盘变成CD驱动器的非正常修复方法
  5. 分布式缓存(Redis)连杀
  6. 关于source insight、添加.s和.S文件,显示全部路径、加入项目后闪屏幕
  7. word中参考文献编号添加及更新方法
  8. 串口流控制DCB结构体解析及设置
  9. redis排查读取超时、连接超时
  10. 百度地图API-覆盖物