题目选自于洛谷能力提升综合题单
题目大多是入门必做模板题经典题,最近开始刷数学部分,我选了大部分题目写下题解(会长期更新…
Part6.2.1~6.2.2 素数和最大公约数
思路:题目给了一个提示 伯特兰-切比雪夫定理,利用定理可以得知,对于所有大于
1
1
1的整数
n
n
n,至少存在一个质数
p
p
p,符合
n
<
p
<
2
n
n < p < 2n
n<p<2n。
我们可以确定答案不是1就是2。如果第0天得知的数字是合数,那么第一天可以告诉与其互质的质数,第二天得知的质数会告诉剩余的合数;如果第0天得知的数字是质数,如果
(
n
+
1
)
/
(
k
+
1
)
>
1
(n+1)/(k+1)>1
(n+1)/(k+1)>1的话,说明这个序列存在与第0天质数的倍数,第一天告诉与其互质的质数,由定理可得
k
+
1
k+1
k+1到其倍数之前存在的质数,肯定能在第二天告诉所有剩余数,如果
(
n
+
1
)
/
(
k
+
1
)
=
1
(n+1)/(k+1)=1
(n+1)/(k+1)=1说明一天即可告诉所有人(很适合当数论签到题
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10,mod=1e9+7;
typedef long long ll;
ll n,k;
bool is_prime(ll x){
for(ll i=2;i<=x/i;i++){
if(x%i==0) return false;
}
return true;
}
int main(){
cin>>n>>k;
if(is_prime(k+1)) {
if((n+1)/(k+1)==1) cout<<"1"<<endl;
else cout<<"2"<<endl;
}
else cout<<"2"<<endl;
return 0;
}
思路:规定一个n,选两个数使得它们最小公倍数最大,肯定是 n × ( n − 1 ) n\times (n-1) n×(n−1) ,注意 n n n等于1特判
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10,mod=1e9+7;
typedef long long ll;
ll n,t;
int main(){
cin>>t;
while(t--){
cin>>n;
if(n==1) cout<<"1"<<endl;
else cout<<n*(n-1)<<endl;
}
return 0;
}
思路:题目大意就是从 n n n个数里选 k k k个数,求它们的最大公约数最大值, k k k从 1 ~ n 1~n 1~n遍历。 n n n个数的公约数,就意味着这 n n n个数都有这个因数,那我们可以用 c n t cnt cnt数组记录每个因数的个数, n n n个数选一个数的公约数的最大值是这个数列最大值 m a x n maxn maxn,然后我们使 k k k增大, m a x n maxn maxn自然减小,查询 c n t [ m a x n ] cnt[maxn] cnt[maxn]是否等于 k k k即可
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10,mod=1e9+7;
typedef long long ll;
int n,a[N],cnt[N];
void get_cnt(int x){
for(int i=1;i<=x/i;i++){
if(x%i==0) {
cnt[i]++;
if(x/i!=i) cnt[x/i]++;
}
}
}
int main(){
int maxn=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
maxn=max(maxn,a[i]);
}
for(int i=1;i<=n;i++) get_cnt(a[i]);
for(int i=1;i<=n;i++){
while(cnt[maxn]<i) maxn--;
cout<<maxn<<endl;
}
return 0;
}
思路:我们要求满足的条件的 x x x个数,用式子表达即为: g c d ( x , a 0 ) = a 1 gcd(x,a_0)=a_1 gcd(x,a0)=a1, g c d ( x , b 0 ) ∗ b 1 = x ∗ b 0 gcd(x,b_0)*b_1=x*b_0 gcd(x,b0)∗b1=x∗b0显然 x x x是 b 1 b_1 b1的因数,那我们枚举 b 1 b_1 b1的因数满足上满两个条件时 a n s + + ans++ ans++即可
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,a0,a1,b0,b1;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int cal(int x){
if(x%a1!=0) return 0;
else if(gcd(x,a0)==a1 && gcd(x,b0)*b1==b0*x) return 1;
else return 0;
}
int main(){
scanf("%d",&n);
while(n--){
scanf("%d %d %d %d",&a0,&a1,&b0,&b1);
ll ans=0;
for(int i=1;i<=b1/i;i++){
if(b1%i==0){
ans+=cal(i);
if(b1/i!=i) ans+=cal(b1/i);
}
}
printf("%lld\n",ans);
}
return 0;
}
思路:大数GCD,高精度数论题,当个板子吧(不喜欢做高精度题目
Code:
#include <stdio.h>
#include <cstring>
#include <iostream>
using std::swap;
const int BASE = 100000000;
const int MAXN = 10005;
char s[MAXN];
int cnt;
template<typename _t>
inline _t read(){
_t x=0,f=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch == '-') f=-f;
for(;isdigit(ch);ch=getchar()) x = x*10+(ch^48);
return x*f;
}
struct bignum{
long long a[MAXN],len;
bignum(){memset(a,0,sizeof a);len = 0;}
inline bool operator < (const bignum & b)const{
if(len != b.len) return len < b.len;
for(int i = len;i>=1;i--) if(a[i] != b.a[i]) return a[i] < b.a[i];
return 0;
}
inline bool operator == (const bignum & b)const{
if(len != b.len) return 0;
for(int i = len;i>=1;i--) if(a[i] != b.a[i]) return 0;
return 1;
}
inline bool operator != (const bignum & b)const{return *this == b ? 0:1;}
inline void operator = (const char *x){
register int tmp=strlen(x),t=1,k=0,js=0;
for(int i=tmp-1;i>=0;--i){
k+=t*(x[i]-'0'),t*=10;
if(t==BASE) t=1,a[++len]=k,k=0;
}
if(k) a[++len]=k;
}
inline bignum operator - (const bignum &c)const{
bignum ans; ans.len = len; bignum b = *this;
for(register int i = 1;i<=c.len||i<=len;i++) {
if(b.a[i] < c.a[i]) -- b.a[i+1] , b.a[i] += BASE;
ans.a[i] = b.a[i] - c.a[i];
}
while(ans.a[ans.len] == 0 && ans.len > 1) -- ans.len;
return ans;
}
inline bignum operator / (const int x){
bignum ans = *this;
for(int i = len;i>=1;i--) ans.a[i-1] += ans.a[i] % x * BASE,ans.a[i] /= x;
while(!ans.a[ans.len] && ans.len > 1) -- ans.len;
return ans;
}
inline bignum operator * (const int x){
bignum ans; ans.len = ++ len;
for(int i = 1;i<=ans.len;i++) {
ans.a[i] += a[i] * x; ans.a[i+1] += ans.a[i]/BASE; ans.a[i] %= BASE;
}
while(!ans.a[ans.len] && ans.len > 1) -- ans.len;
return ans;
}
inline bool Judge(){return a[1] & 1;}
inline void print(){printf("%lld",a[len]);for(register int i = len-1;i>=1;i--) printf("%08lld",a[i]);printf("\n");}
inline void in(){scanf("%s",s);*this=s;}
}a,b;
inline bool Judge(){
if(!a.Judge() && !b.Judge()) {a = a / 2,b = b / 2,++ cnt;return 1;}
if(!a.Judge()) {a = a / 2;return 1;}
if(!b.Judge()) {b = b / 2;return 1;}
return 0;
}
int main(){
a.in();b.in();
while(a != b) {
while(Judge());
if(a == b) break;
if(a<b) swap(a,b);
a = a - b;
} register int num1 = cnt / 25, num2 = cnt % 25 , full = 1<<25;
while(num1) --num1,a = a * full;
while(num2) --num2,a = a * 2;
a.print();
}