acm寒假集训第四讲总结

1.有理数取余

思路:
由题意,答案为b在模19260817下的乘法逆元,使用扩展欧几里得算法求出答案,注意x可能为负数的情况即可

代码:

#include <bits/stdc++.h>
#include <tuple>
using namespace std;
inline int getint()
{
	int res=0,ch=getchar();
	while(!isdigit(ch)&&ch!=EOF){
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+ch-'0';
		res%=19260817;
		ch=getchar();
	}
	return res;
}

 std::tuple<long long, long long, long long> extendedGCD(long long a, long long b) {
 if (b == 0)
 return {a, 1, 0};
 auto [g, x1, y1] = extendedGCD(b, a % b);
 long long x = y1;
 long long y = x1 - (a / b) * y1;
 return {g, x, y};
 }

int main()
{
	int a,b;
	a=getint();b=getint();
	auto [d,x,y]=extendedGCD(b,19260817);
	if(d==1)
	{
		long long inv=(x%19260817+19260817)%19260817;
        cout<<(inv*a)%19260817;
	}
	else
	{
		cout<<"Angry!";
	}
	return 0;
}

2.Minimal Coprime

思路:
观察得,每组数据的答案为r-l,由于[l,r]区间中的每个整数k和k+1都构成一个最小互质区间,所以答案就是r-l,注意l和r等于1的情况

代码:

#include <bits/stdc++.h>
using namespace std;
int main() 
{
    int t;
    cin>>t;
    while(t--) 
	{
        int l,r;
        cin>>l>>r;
        if(l==1&&r==1)
        {
        	cout<<"1"<<endl; 
		}
        else
        {
        	cout<<(r-l)<<endl;
		}
    }
    return 0;
}

3.素数密度

思路:
使用线性筛筛选出小于等于50000(最大值开根号)的所有素数,在利用这些素数筛出区间内的素数数量即可

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int M = 1000005; 
const int N = 50005;
bool a[M], ans[M];
long long cnt = 0, pri[N];
long long L, R;

void prime(int n) 
{
    for (int i = 2; i <= n; ++i)
        if (!a[i]) 
        {
            pri[++cnt] = i;
            for (int j = i << 1; j <= n; j += i) 
                a[j] = 1;
        }
}

int main()
{
    prime(50000); 
    cin >> L >> R;
    L += (L == 1); 
    if (L > R)
    {
        cout << "0" << endl;
        return 0;
    }
    memset(ans, 0, sizeof(ans)); 
    for (register int i = 1; i <= cnt && pri[i] * pri[i] <= R; i++) 
    {
        for (long long j = max(2 * 1ll, (L - 1) / pri[i] + 1) * pri[i]; j <= R; j += pri[i])
            if (j - L >= 0) ans[j - L] = 1;
    }
    int tot = 0;
    for (int i = 0; i <= R - L; i++) 
        if (!ans[i]) tot++;
    cout << tot << endl;
    return 0;
}

4.最大公约数和最小公倍数问题

思路:
由题意,只要计算出y0/x0的所有因子即可,注意相等和相除后不是整数的情况

代码:

#include <bits/stdc++.h>
using namespace std;
int gcd(int a,int b)
{
	int r;
	while(b!=0)
	{
		r=a%b;
 		a=b;
 		b=r;
	}
  	return a;
}
int main()
{
	int x0,y0,i;
	cin>>x0>>y0;
	int k=y0/x0;
	if(y0%x0!=0)
	{
		cout<<"0";
		return 0;
	}
	if(x0==y0)
	{
		cout<<"1";
		return 0;
	}
	int cnt=0;
	for(i=1;i<=sqrt(k);i++)
	{
        if(k%i==0) 
		{
            int a=i;
            int b=k/i;
            if(gcd(a,b)==1) 
			{ 
                cnt++;
            }
        }
    }
    cnt=cnt*2;
    cout<<cnt;
}

学习总结:
通过这次的学习,我学习了数论的一些基本概念,包括gcd的计算,扩展欧几里得算法,线性筛和乘法逆元等,通过解题体会了数学的魅力,通过数学优化算法提高效率

posted @ 2025-02-10 23:05  asdadsdf  阅读(30)  评论(0)    收藏  举报