2017新疆ICPC现场赛K.Sum of the Line
题意:
思路:先推推柿子
i^2的和不是积性函数,不能线性筛= =(强行分开筛感觉很麻烦)
这个柿子不会往下化简了。。但是化到这里已经可以做了
第一种思路:预处理mu,对每个n枚举d 暴力搞一波
这种思路不行,1e8的O(n)mu预处理都快T了QAQ
第二种思路:
考虑mu的定义,我们只需枚举所有对ans有贡献的n的因子d
那什么是有贡献的d呢?
这些d能写成不重复素数的乘积
比如d=30=2*3*5,mu(30)=-1,ok
像d=45=3*3*5就不是有贡献的d,mu(45)=0;
假设我们对n分解质因子之后得到p1=2,p2=7.....
选奇数个p形成的d,mu(d)=-1
选偶数个p形成的d,mu(d)=1
这就是为什么莫比乌斯函数mu也可以叫做容斥因子了。
素数预处理sqrt(1e8)以内的就可以了
2*3*5*7*11*13*17*19*23>1e8
即n最多只有9个质因子
容斥2^9种状态无压力~
复杂度O(10000+T*(512+logn))
难度0.85
c++247ms
#include<iostream>
#include<stdio.h>
#include<vector>
#define ll long long
using namespace std;
const int maxn=1e4+5;
const int mod=998244353;
ll pri[3005];
bool isp[maxn];
ll mu[maxn];
int p=0;
ll inv6;
vector<int>dd;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll qmod(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1)
res=res*a%mod;
a=a*a%mod;
b=b>>1;
}
return res;
}
void get(ll n)
{
isp[1]=1;
mu[1]=1;
for(ll i=2;i<=n;i++)
{
if(!isp[i])
{
pri[++p]=i;
mu[i]=-1;
}
for(ll j=1;j<=p&&i*pri[j]<=n;j++)
{
isp[i*pri[j]]=1;
if(i%pri[j]==0)//不互质
{
mu[i*pri[j]]=0;
}
else
{
mu[i*pri[j]]=-mu[i];
}
}
}
}
void get2(int n)
{
for(int i=1;i<=p&&n>1;i++)
{
if(n%pri[i]==0)
{
dd.push_back(pri[i]);
n/=pri[i];
}
while(n%pri[i]==0)
{
n/=pri[i];
}
}
if(n!=1)
dd.push_back(n);
}
ll s(ll n)
{
ll ans=(((n*(2*n+1)%mod)*(n+1))%mod*inv6)%mod;
return ans;
}
int dfs(int n)
{
int ans=0;
for(int i=1;i<=n;i++)
{
if(n%i==0)
{
ans+=i*i*mu[i]*s(n/i);
}
}
return ans;
}
int main()
{
//cout<<2*3*5*7*11*13*17*21*23<<endl;
inv6=qmod(6,mod-2);
get(10000);
// cout<<p<<endl;
// for(int i=1;i<=100;i++)
// {
// printf("%d\n",dfs(i));
// }
int T;
cin>>T;
while(T--)
{
ll n;
scanf("%lld",&n);
dd.clear();
get2(n);
// for(int i=0;i<dd.size();i++)
// printf("p:%d\n",dd[i]);
ll ans=0;
for(int i=0;i<(1<<dd.size());i++)
{
int t=1;int cnt=0;
for(int j=0;j<dd.size();j++)
{
if(i&(1<<j))
{
t*=dd[j];
cnt++;
}
}
// printf("test:%d\n",t);
if(cnt%2==0)
ans+=1ll*t*t*s(n/t),ans%=mod;
else
ans-=1ll*t*t*s(n/t),ans=(ans+mod)%mod;
}
printf("%lld\n",(ans+mod)%mod);
// puts("");
}
}