【题解】HDU6760 Math is Simple (差分)
【题解】HDU6760 Math is Simple (差分)
好nb的题啊
求\(n\le 1e8\),
\[f(n)=\sum_{1\le a<b \le n,a\perp b,a+b\ge n} {1\over ab}
\]
\(T\le 1e4\)组询问(但是你他吗std不是\(O(n)\)的复杂度吗)
那么
\[f(n)=f(n-1)+\sum_{i\perp n}{1\over in}-\sum_{a<b,a+b=n-1,q\perp b} {1\over ab}
\]
设\(g(n)=\sum_{a<b,a+b=n,a\perp b} {1\over ab}\)
其实
\[g(n)={1\over n}\sum_{1\le a<b\le n,a+b=n,a\perp b} {a+b\over ab}={1\over n}\sum_{a\perp n-a}{1\over a}={1\over n}\sum_{a\perp n}{1\over a}
\]
所以
\[f(n)=f(n-1)+g(n)-g(n-1)
\]
所以
\[f(n)=\cases{
1 & n=1
\\
{1\over 2} & n=2
\\
g (n)+{1\over 2} & otherwise
}
\]
然后他妈的"You can pre-calculate all \(h_{0\dots 10^8}\) values in a second, or so."
//@winlere
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#pragma GCC optimize(3)
using namespace std; typedef long long ll;
int qr(){
int ret=0,c=getchar(),f=0;
while(!isdigit(c)) f|=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int mod=998244353;
const int inv2=(mod+1)/2;
int h[int(1e8+5)],M[int(1e4+5)],REM[int(1e4+5)];
int MOD(const int&x){return x>=mod?x-mod:x;}
int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
int mu(int n){
int ret=0;
for(int t=2;t*t<=n;++t)
if(n%t==0){
int cnt=0;
while(n%t==0) n/=t,++cnt;
if(cnt>1) return 0;
++ret;
}
if(n>1) ++ret;
return ret&1?-1:1;
}
int main(){
h[1]=1;
for(int t=2;t<=1e8;++t){
int g=mod/t;
h[t]=MOD(mod-g,h[mod-g*t]);
}
for(int t=2;t<=1e8;++t) h[t]=MOD(h[t-1]+h[t]);
int T=qr();
while(T--){
int n=qr();
ll ans=0;
if(n==2){printf("%d\n",inv2); continue;}
for(int t=1;t*t<=n;++t)
if(n%t==0){
int g=n/t;
ans+=MOD(h[g],mu(t)*(h[t]-h[t-1]));
if(t*t!=n) ans+=MOD(h[t],mu(g)*(h[g]-h[g-1]));
}
printf("%d\n",MOD(MOD(h[n]-h[n-1]+mod,ans%mod+mod)+inv2));
}
return 0;
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!