「HDU 2841」題解
阿新 • • 發佈:2021-08-17
Description
求給定的 n 行 m 列的矩陣中,從(0,0)可以看到的點的數量。
其中 \(1\leq n,m\leq10^5\)。
Solution
如果一個點 (x,y) , x 與 y 不互質,設 \(\operatorname{GCD(x,y)}=z\),則 (x/z,y/z) 一定會擋住 (0,0) 的視線。
(兩點在同一直線上)
則題目轉化為:求 \(\operatorname{[1,n]}\) 中每個數與 \(\operatorname{[1,m]}\) 中的數互質的個數的和。
做法可以參考:HDU 4135。
總時間複雜度:\(\omicron(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.}\)