【bzoj2820】YY的GCD
因为我没有BZOJ的权限号,所以我的代码只是过了样例,所以具体的细节我也不知道过没有,所以看我博客的同学要是不麻烦的话可以交一下我的代码。。
Description
神犇YY虐完数论后给傻×kAc出了一题
给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
kAc这种傻×必然不会了,于是向你来请教……
多组输入
Input
第一行一个整数T 表述数据组数
接下来T行,每行两个正整数,表示N, M
Output
T行,每行一个整数表示第i组数据的结果
Sample Input
2
10 10
100 100
10 10
100 100
Sample Output
30
2791
2791
HINT
T = 10000
N, M <= 10000000
题解: 这个题还是老套路就是还是把f(n)当成gcd(x,y)=n有多少对,那么我们就能很明显的看出F(n)的含义,就是n|gcd(x,y)的数量。
所以的话刚开始的时候我们还是应该先把方程写下来的,这样子的话我们才能根据方程进行公式推导,我们先把重要的方程写下来。。
待续
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=10000001; ll mu[N],g[N]; int vis[N],prime[N]; int cnt; void Init() { memset(vis,0,sizeof(vis)); mu[1] = 1; cnt = 0; for(int i=2; i<N; i++) { if(!vis[i]) { prime[cnt++] = i; mu[i] = -1; } for(int j=0; j<cnt&&i*prime[j]<N; j++) { vis[i*prime[j]] = 1; if(i%prime[j]) mu[i*prime[j]] = -mu[i]; else { mu[i*prime[j]] = 0; break; } } } g[1]=0; for(int i=0;i<cnt;i++) { for(int j=prime[i];j<N;j+=prime[i]) { g[j]+=mu[j/prime[i]]; } } for(int i=1;i<N;i++) g[i]+=g[i-1]; } void slove(int n,int m) { if(n>m) swap(n,m); ll ans=0; int r; for(int i=1;i<=n;i=r+1) { r=min(n/(n/i),m/(m/i)); ans+=(g[r]-g[i-1])*(n/i)*(m/i); } cout<<ans<<endl; } int main() { int t; int n,m; Init(); scanf("%d",&t); for(int i=1;i<=t;i++) { scanf("%d%d",&n,&m); slove(n,m); } }