题目链接:https://www.acwing.com/problem/content/217/
很棒的题解:https://www.acwing.com/solution/content/63012/
大意是给出abd,求存在多少x<=a,y<=b使得gcd(a,b)=d。
问题可以转化为存在多少gcd(a/d,b/d)=1。
问题可以满足容斥定理,容斥的符号正好是莫比乌斯的符号。
但是效率并不理想,可以达到n^2。因为存在a'/i在区间上存在整除情况,因此可以分块处理,这样我们总能进行一步预处理,O(1)的得到某一个块中的值。
总体复杂度可以达到n/^n。比较郁闷的是容斥的部分还是需要再好好康康。
code:
const int nn = 5e4+10; int miu[nn]; int v[nn]; int s[nn]; void mobi(int n){ //miu[i] = 0,存在相等的质因子(即存在平方因子); //= 1,所有质因子各不相等且质因子数量为偶数; //= -1,所有质因子各不相同且质因子数量为奇数。 for(int i=1;i<=n;i++) miu[i] = 1,v[i] = 0; for(int i=2;i<=n;i++){ if(v[i]) continue; miu[i] = -1; for(int j=2*i;j<=n;j+=i){ v[j] = 1; if((j/i)%i==0) miu[j] = 0; else miu[j]*=-1; } } for(int i=1;i<=n;i++){ s[i] = s[i-1]+miu[i]; } } int main() { //cin.ignore(numeric_limits<streamsize>::max(),'\n'); ios_base::sync_with_stdio(0); cin.tie(0); //cout.tie(0); mobi(nn-3); int n; cin>>n; int a,b,d; for(int i=1;i<=n;i++){ cin>>a>>b>>d; int ta = a/d,tb = b/d; int tn = min(ta,tb); // 实际上就是求gcd(ta,tb)==1 ll ans = 0; for(int l=1,r;l<=tn;l=r+1){ r = min(tn,min(ta/(ta/l),tb/(tb/l))); ans+=(s[r]-s[l-1])*(ll)(ta/l)*(ll)(tb/l); } cout<<ans<<endl; } }