放松型休闲无脑小清新签到题

题目大意:

\(\sum_{i=1}^n\sum_{j=1}^n [gcd(i,j)是质数]*gcd(i,j)^k,1\leq n\leq 10^9,1\leq k\leq 100\)

题解:

\(f[x]=[x是质数]*x^k,F[x]=\sum_{i=1}^{x}f[i]\)
\(\sum_{i=1}^{n}\sum_{j=1}^{n}f[gcd(i,j)]=\sum_{d=1}^{n}f[d]\sum_{i=1}^{n}\sum_{j=1}^{n}[gcd(i,j)=d]\)
\(=\sum_{d=1}^{n}f[d]\sum_{i=1}^{ \left\lfloor{\frac{n}{d}}\right\rfloor}\sum_{j=1}^{ \left\lfloor{\frac{n}{d}}\right\rfloor}e[gcd(i,j)]=\sum_{d=1}^{n}f[d]\sum_{i=1}^{ \left\lfloor{\frac{n}{d}}\right\rfloor}\sum_{j=1}^{ \left\lfloor{\frac{n}{d}}\right\rfloor}\sum_{e|i,e|j}^{}μ[e]\)
\(=\sum_{d=1}^{n}f[d]\sum_{e=1}^{ \left\lfloor{\frac{n}{d}}\right\rfloor}{ \left\lfloor{\frac{n}{de}}\right\rfloor}^{2}=\sum_{(t=de)=1}^{n}{ \left\lfloor{\frac{n}{t}}\right\rfloor}^{2}\sum_{de=t}^{}f[d]*μ[e]\)
分块,需要求\(G[x]=\sum_{t=1}^{x}\sum_{de=t}^{}f[d]*μ[e]=\sum_{e=1}^{x}μ[e]\sum_{d=1}^{ \left\lfloor{\frac{x}{e}}\right\rfloor}f[d]\sum_{e=1}^{x}μ[e]F[\left\lfloor{\frac{x}{e}}\right\rfloor]\)
再分块,需要求\(F[x]\)
发现和质数有关,考虑\(Min25\)筛。初始时需要自然数幂和,要伯努利数。
另:为卡常,可预处理部分\(F[]\)或不用\(Map\)记忆化杜教筛。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int MOD=998244353;
int add(int a,int b)
{a+=b;return a>=MOD?a-MOD:a;}
int sub(int a,int b)
{a-=b;return a<0?a+MOD:a;}
int mul(int a,int b)
{return 1LL*a*b%MOD;}
int gcd(int a,int b)
{return b?gcd(b,a%b):a;}
int ksm(int a,int b)
{
    int ans=1;
    for(;b;b>>=1,a=mul(a,a))
        if(b&1)ans=mul(ans,a);
    return ans;
}
int n,k;
int s;
const int Q=1<<17;
int id1[Q],id2[Q],p[1<<18];
int ch[Q],mu[1<<20];
int tot=0;
int c[1<<7][1<<7];
int b[1<<7];
int f[Q];
int Gid(int x)
{return x<=s?id1[x]:id2[n/x];}
namespace Min25{
    int val[Q];
    int smf[Q];
    int inv[1<<7];
    int ch[1<<20]={0};
    void Prime(){
        int maxn=1e6;
        mu[1]=1;
        for(int i=2;i<=maxn;i++){
            if(!ch[i])p[++tot]=i,mu[i]=MOD-1;
            for(int j=1,t;j<=tot&&(t=i*p[j])<=maxn;j++){
                ch[t]=1;
                if(i%p[j]==0){
                    mu[t]=0;
                    break;
                }
                mu[t]=sub(0,mu[i]);
            }
        }
        for(int i=2;i<=maxn;i++)mu[i]=add(mu[i],mu[i-1]);
        for(int i=1;i<=tot;i++)
            if(p[i]>s){
                tot=i-1;
                return;
            }
    }
    void Bo(){
        for(int i=0;i<=123;i++){
            c[i][0]=1;
            for(int j=1;j<=i;j++)
                c[i][j]=add(c[i-1][j-1],c[i-1][j]);
        }
        b[0]=1;
        inv[1]=1;
        for(int i=1;i<=111;i++){
            int tmp=0;
            for(int j=0;j<i;j++)
                tmp=add(tmp,mul(c[i+1][j],b[j]));
            inv[i+1]=ksm(i+1,MOD-2);
            b[i]=mul(inv[i+1],sub(0,tmp));
        }
    }
    int Psum(int x){
        if(x<0){
            int als=0;
            for(int i=1;i<=x;i++)
                als=add(als,ksm(i,k));
            return als;
        }
        int als=0;
        x=(x+1)%MOD;
        for(int i=1,ow=x;i<=k+1;i++)
            als=add(als,mul(mul(c[k+1][i],b[k+1-i]),ow)),ow=mul(ow,x);
        return mul(inv[k+1],als);
    }
    void Init(){
        int maxn=0;
        Prime();Bo();
        for(int i=1,p1,p2;i<=n;i=p2+1)
        {
            p1=n/i,p2=n/p1;
            if(p1<=s)id1[p1]=++maxn;
            else id2[p2]=++maxn;
            val[maxn]=p1;
            f[maxn]=sub(Psum(p1),1);
        }
        for(int j=1;j<=tot;j++){
            int pr=p[j],owo=ksm(pr,k);
            smf[j]=add(smf[j-1],owo);
            for(int i=1;i<=maxn&&pr*pr<=val[i];i++)
                f[i]=sub(f[i],mul(owo,sub(f[Gid(val[i]/pr)],smf[j-1])));
        }
    }
}
int Res[1<<12];
int Gmu(int x)
{
    if(x<=1000000)return mu[x];
    if(Res[n/x])return Res[n/x]; 
    int als=0;
    for(int i=2,las;i<=x;i=las+1){
        las=x/(x/i);
        als=add(als,mul((las-i+1),Gmu(x/i)));
    }
    als=sub(1,als);
    return (Res[n/x]=als);
}
void Test(){
    int ppp;
    cin>>ppp;
    for(int i=1;i*i<=ppp;i++)
        if(ppp/(ppp/i)!=i)exit(0);
    Test();
}
int Gsum(int x)
{
    int als=0;
    for(int i=1,las;i<=x;i=las+1){
        las=x/(x/i);
        als=add(als,mul(sub(Gmu(las),Gmu(i-1)),f[Gid(x/i)]));
    }
    return als;
}
int main()
{
    cin>>n>>k;
    s=sqrt(n)+1;
    Min25::Init();
    int als=0;
    for(int i=1,las,lv=0,nv;i<=n;i=las+1){
        las=n/(n/i);
        nv=Gsum(las);
        als=add(als,mul(mul(n/i,n/i),sub(nv,lv)));
        lv=nv;
    }
    printf("%d",als);
    return 0;
}
posted @ 2019-02-20 21:31 蒟蒻小果冻 阅读(...) 评论(...)  编辑 收藏