「HDU 2841」题解
Description
求给定的 n 行 m 列的矩阵中,从(0,0)可以看到的点的数量。
其中 \(1\leq n,m\leq10^5\)。
Solution
如果一个点 (x,y) , x 与 y 不互质,设 \(\gcd(x,y)=z\),则 (x/z,y/z) 一定会挡住 (0,0) 的视线。
(两点在同一直线上)
则题目转化为:求 \(\operatorname{[1,n]}\) 中每个数与 \(\operatorname{[1,m]}\) 中的数互质的个数的和。
做法可以参考:HDU 4135。
总时间复杂度:\(\Theta(T\sqrt n)\)。
Code:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN=1e6;
#define int long long
int t,a,b,n,cnt,k,mp[MAXN+5],p[MAXN+5],ans[MAXN+5],num[MAXN+5],phi[MAXN+5],sum[MAXN+5],v[MAXN+5],tot,pp;
bool vis[MAXN+5];
void Work(int x)
{
tot=0;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
v[++tot]=i;
while(x%i==0)
{
x/=i;
}
}
}
if(x!=1)
{
v[++tot]=x;
}
}
void dfs(int now,int &V,int res,int up,int cc)
{
if(now>tot)
{
if(!cc)
{
return;
}
if(cc&1)
{
V-=up/res;
}
else{
V+=up/res;
}
return;
}
dfs(now+1,V,res*v[now],up,cc+1);
dfs(now+1,V,res,up,cc);
}
int Ans(int x)
{
if(!x)
{
return 0;
}
int val=x,cc=0;
dfs(1,val,1,x,cc);
return val;
}
signed main()
{
scanf("%lld",&t);
while(t--){
int op=0;
scanf("%lld%lld",&a,&b);
for(int i=1;i<=b;i++)
{
Work(i);
int tmp=Ans(a);
op+=tmp;
}
printf("%lld\n",op);
}
return 0;
}
\(\Bbb{End.}\)
\(\Bbb{Thanks}\) \(\Bbb{For}\) \(\Bbb{Reading.}\)
本文来自博客园,作者:{StranGePants},转载请注明原文链接:https://www.cnblogs.com/StranGePants/p/15154407.html