重点是要搞清楚取整符号的性质。[(a+b)/c]=(a-a%c)/c+[(a%c+b)/c]
思路应该是首先明白这是一个反演题,然后尝试把最后一个Σ换成易于表达的式子。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 500050 #define mod 998244353 using namespace std; long long n,m,prime[maxn],tot=0,miu[maxn],ans=0; double x; bool vis[maxn]; void get_prime() { miu[1]=1; for (long long i=2;i<=maxn-50;i++) { if (!vis[i]) {vis[i]=true;miu[i]=-1;prime[++tot]=i;} for (long long j=1;j<=tot && i*prime[j]<=maxn-50;j++) { vis[i*prime[j]]=true; if (i%prime[j]) miu[i*prime[j]]=-miu[i]; else {miu[i*prime[j]]=0;break;} } } } long long f_pow(long long a,long long b) { long long ans=1,base=a; while (b) { if (b&1) ans=(ans*base)%mod; base=(base*base)%mod; b>>=1; } return ans; } long long inv(long long x) {return f_pow(x,mod-2);} int main() { scanf("%lld%lld%lf",&n,&m,&x); get_prime(); if (n>m) swap(n,m); ans=(ans+(n*(n-1)/2)%mod*((m*(m-1)/2)%mod)%mod-m*n%mod+mod)%mod; for (long long d=1;d<=n;d++) { long long a=2*d*(long long)(x/d)+d,b=0;a%=mod; for (long long i=1;i<=n/d;i++) {b+=miu[i]*(n/i/d)*(m/i/d)%mod;b=(b+mod)%mod;} ans=(ans+a*b%mod)%mod;ans=(ans+mod)%mod; } printf("%lld\n",ans*inv(2)%mod); return 0; }