Dirichlet求和


求出的话一般是的复杂度。
可以转移质因子的贡献,优化到的复杂度。


前缀和


知道

for(int i=1;i<=cnt&&pri[i]<=n;i++){
    for(int j=1;j*pri[i]<=n;i++){
        a[j * pri[i]] += a[j];
    }
}

知道

    for(int i = cnt; i ; -- i) {
        for(int j = n / pri[i]; j ; -- j) {
            a[j * pri[i]] -= a[j];
        }
    }

后缀和


知道

    for(int i = 1; i <= cnt && pri[i] <= n; ++ i) {
        for(int j = n / pri[i]; j ; -- j) {
            a[j] += a[j * pri[i]];
        }
    }

知道

    for(int i = cnt; i ; -- i) {
        for(int j = 1; j * pri[i] <= n; ++ j) {
            a[j] -= a[j * pri[i]];
        }
    } 

例题

题目链接


可以用后缀和求出

#include<bits/stdc++.h>
using namespace std;
#define me(a,x) memset(a,x,sizeof(a))
#define sc scanf
#define pr printf
#define IN freopen("in","r",stdin);
#define OUT freopen("out","w",stdout);
typedef long long ll;
typedef unsigned long long ull;
const int N=2e7+6;
const int mod=1e9+7;
int O(){putchar('\n');return 0;}template<typename T,typename... Ty>
int O(const T& a,const Ty&... b){cout<<a<<' ';return O(b...);}
void I(){}template<typename T,typename... Ty>void I(T& a,Ty&... b){cin>>a;I(b...);}
template<typename T>void db(T *bg,T *ed){while(bg!=ed)cout<<*bg++<<' ';pr("\n");}
inline ll mul_64(ll x,ll y,ll c){return (x*y-(ll)((long double)x/c*y)*c+c)%c;}
inline ll ksm(ll a,ll b,ll c){ll ans=1;for(;b;b>>=1,a=a*a%c)if(b&1)ans=ans*a%c;return ans;}
typedef unsigned int uint;
uint phi[N];
int cnt=0,pri[N];
bool vis[N];
uint mu[N];
uint s[N],t[N];
void pre(){
    phi[1]=1;
    mu[1]=1;
    for(int i=2;i<N;i++){
        if(!vis[i])pri[++cnt]=i,phi[i]=i-1,mu[i]=-1;
        for(int j=1;j<=cnt&&i*pri[j]<N;j++){
            vis[i*pri[j]]=true;
            if(i%pri[j]==0){
                phi[i*pri[j]]=phi[i]*pri[j];
                mu[i*pri[j]]=0;
                break;
            }
            phi[i*pri[j]]=phi[i]*phi[pri[j]];
            mu[i*pri[j]]=-mu[i];
        }
    }
}
int main(){
    pre();
    int tt;cin>>tt;
    while(tt--){
        int n,m;
        sc("%d%d",&n,&m);
        for(int i=1;i<=n;i++)s[i]=phi[i]*mu[i];
        for(int i=1;i<=m;i++)t[i]=phi[i]*mu[i];
        for(int i=1;pri[i]<=n||pri[i]<=m;i++){
            if(pri[i]<=n)for(int j=n/pri[i];j;j--)s[j]+=s[j*pri[i]];
            if(pri[i]<=m)for(int j=m/pri[i];j;j--)t[j]+=t[j*pri[i]];
        }
        uint ans=0;
        for(int d=1;d<=min(n,m);d++){
            ans+=mu[d]*s[d]*t[d];
        }
        pr("%u\n",ans);
    }
}
全部评论

相关推荐

点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务