Luogu P3455 [POI2007]ZAP-Queries
由于之前做了Luogu P2257 YY的GCD,这里的做法就十分套路了。
建议先看上面一题的推导,这里的话就略去一些共性的地方了。
还是和之前一样设:
\[f(d)=\sum_{i=1}^a \sum_{j=1}^b[\gcd(i,j)=d]\]
\[F(n)=\sum_{n|d} f(d)=\lfloor\frac{a}{n}\rfloor\lfloor\frac{b}{n}\rfloor\]
还是莫比乌斯反演定理推出:
\[f(n)=\sum_{n|d}\mu(\lfloor\frac{d}{n}\rfloor)F(d)\]
这时我们发现,不像上面一题那么繁琐还要对\(f(n)\)求和,这里\(ans=f(d)\)
所以可以直接开始推导答案:
\[ans=\sum_{d|k}\mu(\lfloor\frac{k}{d}\rfloor)F(k)\]
还是考虑换个东西枚举,我们设\(\lfloor\frac{k}{d}\rfloor=t\),枚举\(t\)则有:
\[ans=\sum_{t=1}^{\min(\lfloor\frac{a}{d}\rfloor,\lfloor\frac{b}{d}\rfloor)}\mu(t)\lfloor\frac{a}{t\cdot d}\rfloor\lfloor\frac{b}{t\cdot d}\rfloor\]
这个式子已经变成\(O(n)\)的了,还是注意到\(\lfloor\frac{a}{t\cdot d}\rfloor\lfloor\frac{b}{t\cdot d}\rfloor\)可以除法分块,然后只需要对莫比乌斯函数做一个前缀和即可单次\(O(\sqrt n)\)。
CODE
#include<cstdio> #include<cctype> #define RI register int using namespace std; const int P=50005; int t,n,m,d,prime[P+5],cnt,mu[P+5],sum[P+5]; long long ans; bool vis[P+5]; class FileInputOutput {private:#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))#define S 1<<21char Fin[S],Fout[S],*A,*B; int Ftop,pt[25];public:FileInputOutput() { A=B=Fin; Ftop=0; } inline void read(int &x){x=0; char ch; int flag=1; while (!isdigit(ch=tc())) flag=ch^'-'?1:-1;while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc())); x*=flag;}inline void write(long long x){if (!x) return (void)(pc(48),pc('\n')); RI ptop=0;while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('\n');}inline void Fend(void){fwrite(Fout,1,Ftop,stdout);}#undef tc#undef pc#undef S }F; #define Pi prime[j] inline void Euler(void) {vis[1]=mu[1]=1; RI i,j; for (i=2;i<=P;++i){if (!vis[i]) prime[++cnt]=i,mu[i]=-1;for (j=1;j<=cnt&&i*Pi<=P;++j){vis[i*Pi]=1; if (i%Pi) mu[i*Pi]=-mu[i]; else break;}}for (i=1;i<=P;++i) sum[i]=sum[i-1]+mu[i]; } #undef Pi inline int min(int a,int b) {return a<b?a:b; } int main() {//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);for (Euler(),F.read(t);t;--t){F.read(n); F.read(m); F.read(d); ans=0; int lim=min(n/d,m/d);for (RI l=1,r;l<=lim;l=r+1){r=min(n/(n/l),m/(m/l)); ans+=1LL*(n/(l*d))*(m/(l*d))*(sum[r]-sum[l-1]);}F.write(ans);}return F.Fend(),0; }转载于:https://www.cnblogs.com/cjjsb/p/9852467.html
总结
以上是生活随笔为你收集整理的Luogu P3455 [POI2007]ZAP-Queries的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 前后台传参类型、格式不同,解决思路
- 下一篇: 在java web项目中实现随项目启动的