题目:http://acm.nyist.net/JudgeOnline/problem.php?pid=471
题意:poj 3090的升级版http://blog.csdn.net/w20810/article/details/43701879只不过给你的不是正方形,而是x*y的矩阵,也是求可见点的个数。
分析:设x<=y,先在左边x*x的区域内,用poj3090的方法计算出可见点的个数,然后剩下的问题就是求在1~x内与n互素的数的个数,其中n:x+1-->y。http://blog.csdn.net/w20810/article/details/43882951
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
typedef long long LL;
LL solve(LL n,LL r) //区间[1,r]内与n互素的数的个数
{
vector<LL> p;
for(LL i=2; i*i<=n; i++)
{
if(n%i==0)
{
p.push_back(i);
while(n%i==0) n/=i;
}
}
if(n>1)
p.push_back(n);
LL ans=0;
for(LL msk=1; msk<(1<<p.size()); msk++)
{
LL multi=1,bits=0;
for(LL i=0; i<p.size(); i++)
{
if(msk&(1<<i)) //判断第几个因子目前被用到
{
++bits;
multi*=p[i];
}
}
LL cur=r/multi;
if(bits&1) ans+=cur;
else ans-=cur;
}
return r-ans;
}
const int maxn=100001;
LL phi[maxn];
void dophi()
{
LL i,j,k;
for(i=1;i<maxn;i++) phi[i]=i;
for(i=2;i<maxn;i+=2) phi[i]/=2;
for(i=3;i<maxn;i+=2)
if(phi[i]==i)
for(j=i;j<maxn;j+=i)
phi[j]=phi[j]/i*(i-1);
}
int main()
{
dophi();
for(int i=2;i<maxn;i++)
phi[i]+=phi[i-1];
LL x,y,ans;
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%lld%lld",&x,&y);
if(x<y)
swap(x,y);
ans=phi[y]*2-1;
LL ans1=0;
for(int i=y+1;i<=x;i++)
ans1+=solve(i,y);
printf("%lld\n",ans+ans1);
}
return 0;
}