Comprehensive problem list for improving ability (Part 6.2)

The topic is selected from Comprehensive questionnaire for improving Luogu's ability
Most of the questions are classic template questions for entry. Recently, I began to brush the mathematics part. I chose most of the questions and wrote down the solution (which will be updated for a long time

Part6.2.1~6.2.2 prime and maximum common divisor

Idea: the title gives a hint Bertrand Chebyshev theorem , using the theorem, we can know that for all greater than 1 1 Integer of 1 n n n. At least one prime number exists p p p. Accord with n < p < 2 n n < p < 2n n<p<2n.
We can be sure that the answer is either 1 or 2. If the number we know on day 0 is a composite number, we can tell its coprime prime number on the first day, and the prime number we know on the second day will tell the remaining composite number; if the number we know on day 0 is a prime number, if ( n + 1 ) / ( k + 1 ) > 1 (n+1)/(k+1)>1 If (n + 1) / (K + 1) > 1, it means that the sequence has a multiple of the prime number on day 0. On the first day, tell the prime number that is coprime with it, which can be obtained from the theorem k + 1 k+1 The prime number existing before k+1 to its multiple can certainly tell all the remaining numbers the next day, if ( n + 1 ) / ( k + 1 ) = 1 (n+1)/(k+1)=1 (n+1)/(k+1)=1 means you can tell everyone in one day

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;
}

Idea: specify an n and choose two numbers so that their least common multiple is the largest. It must be n × ( n − 1 ) n\times (n-1) n × (n − 1), note n n n equals 1 special judgment

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;
}

Idea: the main idea of the topic is from n n Select from n numbers k k k numbers, find their maximum common divisor, k k k from 1 ~ n 1~n 1 ~ n traversal. n n The common divisor of n numbers means this n n If n numbers have this factor, we can use it c n t cnt cnt array records the number of each factor, n n n numbers the maximum value of the common divisor of a number is the maximum value of this number sequence m a x n maxn maxn, and then we make k k k increases, m a x n maxn maxn natural reduction, query c n t [ m a x n ] cnt[maxn] cnt[maxn] is equal to k k k is enough

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;
}

Train of thought: we need to meet the conditions x x The number of x, expressed by the formula, is: 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 is b 1 b_1 The factor of b1, let's enumerate b 1 b_1 When the factor of b1 satisfies the above two conditions 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

Idea: large number GCD, high-precision number theory problem, be a board (I don't like high-precision problem)

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();
}

Posted on Sun, 07 Nov 2021 19:59:45 -0500 by mumford