Visible Trees
题意: N*M的格点上有树(从1开始),从0,0点可以看到多少棵树。
gcd(x,y)!=1的格子看不到。
对每一列分别去求那些行的格子可以看到。
先预处理出1到m的素因子,然后利用容斥原理,对于行数是(偶数个素因子的积)的倍数的行,加上,否则减去。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int maxn=100010; 5 vector<int> pri[maxn]; 6 int que[maxn]; 7 8 void init(){ 9 for(int i=2;i<maxn;i++){ 10 pri[i].clear(); 11 int temp=i; 12 for(int j=2;j*j<=i;j++) if(temp%j==0){ 13 pri[i].push_back(j); 14 while(temp%j==0) temp/=j; 15 } 16 if(temp>1) pri[i].push_back(temp); 17 } 18 } 19 ll solve(int n,int s){ 20 int cnt=0; 21 que[cnt++]=1; 22 for(int i=0;i<pri[s].size();i++){ 23 int v=pri[s][i]; 24 if(v>n) break; 25 int k=cnt; 26 for(int j=0;j<k;j++){ 27 que[cnt++]=que[j]*v*(-1); 28 } 29 } 30 ll sum=0; 31 for(int i=0;i<cnt;i++) sum+=n/que[i]; 32 return sum; 33 } 34 35 int main(){ 36 int t; 37 init(); 38 scanf("%d",&t); 39 while(t--){ 40 int n,m; 41 scanf("%d%d",&n,&m); 42 ll ans=n; 43 for(int i=2;i<=m;i++) ans+=solve(n,i); 44 printf("%lld ",ans); 45 } 46 }