题外话:
当时我们老师要我们三个人出一套题目给
noi
集训,然后我们当时就吓尿了!!!各种担心出的题目太水被秒。。。。。然而事实上效果还不错,只有
yyt
一位爷
A
掉了,悲伤的是
距离这道题目出现已经很久了,正好刚刚搭的新博客,所以就来水一发题解。
description:
计算
∑Nn=1∑Mm=1∑m−1k=0⌊nk+xm⌋
对
998244353
取模的答案。
solution
首先考虑 ∑m−1k=0⌊nk+xm⌋
∑m−1k=0⌊nk+xm⌋=∑m−1k=0(⌊nk−nk%mm⌋+⌊nk%m+xm⌋)=∑m−1k=0nkm−∑m−1k=0nk%mm+∑m−1k=0⌊nk%m+xm⌋
令
gcd(n,m)=d
不难发现,
nk%m
取了
d
遍数列
所以有: ∑m−1k=0⌊nk+xm⌋=∑m−1k=0nkm−∑m−1k=0nk%mm+∑m−1k=0⌊nk%m+xm⌋
=n∗(m−1)2−d∑md−1k=0kdm+d∑md−1k=0⌊kd+xm⌋=n∗(m−1)2−(m−d)2+d∑md−1k=0⌊kmd+xm⌋
根据具体数学上的黑科技: ∑m−1k=0⌊x+km⌋=⌊mx⌋
所以有: ∑m−1k=0⌊nk+xm⌋=n∗(m−1)2−m−d2+d⌊xd⌋=(n∗m−n−m+1+d+2d⌊xd⌋2
之后就是经典的容斥问题了,首先我们枚举 d ,
=∑min(N,M)d=1∑min(Nd,Md)k=1μ(k)∗(a∗b∗d∗⌊xd⌋+ab(a+1)(b+1)∗D24−a(a+1)b∗D2−b(b+1)a∗D2)
其中
a=⌊Nkd⌋,b=⌊Mkd⌋,D=kd
code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const long long Mod=998244353;
long long mu[500010]={0};
int hash[500010]={0};
int prime[500010]={0};
int ptot=0;
long long N,M;
double x;
long long power(long long a,long long k)
{
long long o=1;
for(;k>0;)
{
if(k&1)
o=o*a%Mod;
a=a*a%Mod;
k>>=1;
}
return o;
}
void Pre_()
{
mu[1]=1;
for(int i=2;i<=N;i++)
{
if(hash[i]==0)
{
prime[++ptot]=i;
mu[i]=-1;
}
for(int j=1;prime[j]*i<=N && j<=ptot;j++)
{
hash[prime[j]*i]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
return;
}
int main()
{
cin>>N>>M>>x;
if(N>M) swap(N,M);
Pre_();
long long inv=power(2,Mod-2);
long long ans=0;
for(long long d=1;d<=N;d++)
{
for(long long k=N/d;k>=1;k--)
{
long long a=N/d/k,b=M/d/k,D=k*d;
ans=(ans+mu[k]*((a*(a+1)/2*D%Mod*(b*(b+1)/2*D%Mod)%Mod-a*(a+1)/2*D%Mod*b%Mod-b*(b+1)/2*D%Mod*a%Mod+(((d*((int)(x/d)))<<1)*a*b%Mod+d*a*b%Mod))+(Mod<<1)))%Mod;
}
}
cout<<ans*inv%Mod<<endl;
return 0;
}