数论

P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题(欧几里得)

欧几里得,gcdlcm=xy的应用

#include<cstdio>
#include<iostream>
using namespace std;
int gcd(int a,int b){
	if(b==0) return a;
	return gcd(b,a%b);
}
int cnt;
int main(){
	int x,y;
	scanf("%d%d",&x,&y);
	for(int i=x;i<=y;i++){
		int num=x*y/i;
		if(num*i==x*y&&gcd(num,i)==x) cnt++;
	}
	printf("%d",cnt);
	return 0;
}

P3166 [CQOI2014]数三角形

首先全选:C((n+1)(m+1),3),然后考虑每一行、每一列不应该选的,所以减去(n+1)C((m+1),3)+(m+1)*(C(n+1),3)。

最后考虑整个列上的,则考虑(0,0)到(i,j)这条直线上除两端点外一共有几个整数点,可以发现有gcd(i,j)-1个,注意这些点可能是左下到右上,也可能是左上到右下,所以要*2。

注意此题钟组合数的处理。

#include<cstdio>
#include<iostream>
using namespace std;
const int N=2000005;
typedef long long ll;
int read(){
	int num=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		num=num*10+c-'0';
		c=getchar();
	}
	return num*f;
}
int n,m;
ll gcd(ll a,ll b){
	if(b==0) return a;
	return gcd(b,a%b);
}
ll getc(ll x){
	return x*(x-1)*(x-2)/(3*2);
}
int main(){
	m=read(); n=read();
	ll ans=getc((n+1)*(m+1))-(m+1)*getc(n+1)-(n+1)*getc(m+1);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			ll tmp=2*(n-i+1)*(m-j+1)*(gcd(i,j)-1);
			if(tmp<=0) continue;
			ans-=tmp;
		}
	}
	printf("%lld",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/New-ljx/p/15363981.html