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