zoukankan      html  css  js  c++  java
  • uoj#62 怎样跑的更快 (莫比乌斯反演)

    题目链接:http://uoj.ac/problem/62

    推式子呀推式子

    发现我对莫比乌斯反演一无所知qaq

    预处理出要用的数组,然后反演反演反演就好啦

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 100010;
    const int mod = 998244353,pmod=mod-1;
    
    int n,c,d,q;
    int b[maxn],f[maxn],fr[maxn],g[maxn],h[maxn],ans[maxn];
    
    int qsm(int i,int po){
        int res=1;
        while(po){
            if(po&1) res=1ll*res*i%mod;
            i=1ll*i*i%mod;
            po>>=1;
        } return res;
    }
    
    int isp[maxn],prime[maxn],mu[maxn],tot;
    
    void init(){
        isp[1],mu[1]=1;
        for(int i=2;i<=100000;++i){
            if(!isp[i]){
                prime[++tot]=i;
                mu[i]=-1;
            }
            for(int j=1;j<=tot&&i*prime[j]<=100000;++j){
                isp[i*prime[j]]=1;
                if(i%prime[j]!=0){
                    mu[i*prime[j]]=-mu[i];
                }else{
                    mu[i*prime[j]]=0;
                    break;
                }
            }
        }
        int mi=((c-d)%pmod+pmod)%pmod; // 欧拉定理   处理指数为负 
        for(int i=1;i<=100000;++i) f[i]=qsm(i,mi);
        for(int i=1;i<=100000;++i){
            for(int j=1;i*j<=100000;++j){
                fr[i*j]=((fr[i*j]+1ll*mu[j]*f[i]%mod)%mod+mod)%mod;
            }
        }
        for(int i=1;i<=100000;++i) g[i]=qsm(i,d);
    }
    
    void solve(){
        memset(h,0,sizeof(h));
        memset(ans,0,sizeof(ans));
        
        for(int i=1;i<=n;++i) b[i]=1ll*b[i]*qsm(g[i],mod-2)%mod;
        
        for(int i=1;i<=n;++i){
            for(int j=1;i*j<=n;++j){
                h[i*j]=((h[i*j]+1ll*mu[j]*b[i]%mod)%mod+mod)%mod;
            }
        }
        
        for(int i=1;i<=n;++i){
            if(fr[i]==0&&h[i]!=0){ printf("-1\n"); return; } // 非0数除0无解 
            h[i]=1ll*h[i]*qsm(fr[i],mod-2)%mod;
        }
        
        for(int i=1;i<=n;++i){
            for(int j=1;j*i<=n;++j){
                ans[i]=((ans[i]+1ll*mu[j]*h[i*j]%mod)%mod+mod)%mod;
            }
        }
        
        for(int i=1;i<=n;++i){
            if(ans[i]!=0&&g[i]==0){ printf("-1\n"); return; }
            if(g[i]) ans[i]=1ll*ans[i]*qsm(g[i],mod-2)%mod; // 这里的特判注意一下 
            else ans[i]=0;
        }
        for(int i=1;i<=n;++i){
            printf("%d ",(ans[i]%mod+mod)%mod);
        }printf("\n");
    }
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f;}
    
    int main(){
        n=read(),c=read(),d=read(),q=read();
        init();
        while(q--){
            for(int i=1;i<=n;++i) b[i]=read();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    (Toolbar)Android中如何消除Toolbar左边的空白
    (TextView)Android中为TextView赋初始值
    (Edittext)Android中界面中有多个Edittext,如何默认让第二个获取焦点
    (警告)Android中报Custom view `&#215;&#215;&#215;` has setOnTouchListener called on it but does not override performClick警告
    (Toolbar)Android中app:showASAction的值及含义
    个人课程总结
    (list)关于list清空问题的解决
    Ubuntu hive 安装过程中遇到的一些问题
    学习进度——第十七周
    个人课程总结
  • 原文地址:https://www.cnblogs.com/tuchen/p/10467130.html
Copyright © 2011-2022 走看看