能力提升综合题单Part6 数学(Part 6.2.1~6.2.2)

题目选自于洛谷能力提升综合题单
题目大多是入门必做模板题经典题,最近开始刷数学部分,我选了大部分题目写下题解(会长期更新…

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×(n1) ,注意 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 1n遍历。 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=xb0显然 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;
}

P2152 [SDOI2009]SuperGCD

思路:大数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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不会数据库

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值