zoukankan      html  css  js  c++  java
  • 20190730

    互质对

    题意简述

    给你一个长度为 $n$ 的序列。$q$ 次操作,每次将一个数删除或加入,问操作完后的序列互质对个数。

    $n,qleq 10^5,a_ileq 5 imes 10^5$ 。

    $solution:$

    对于数 $xleq 5 imes 10^5$ ,它的质因子个数不超过 $7$ 个,所以直接做简单容斥即可。

    时间复杂度 $O(nsqrt{a})$ 。

    写法优秀的可以为 $O(n imes 2^7)$

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define int long long
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=510001;
    int n,q,cnt,g[MAXN],num[MAXN],M[MAXN];
    inline void dfs(int ps,int res,int ans){
        if(ps==g[0]+1){
            if(res==0) return;
            if(res&1) cnt+=num[ans];
            else cnt-=num[ans];
            return;
        }
        dfs(ps+1,res+1,ans*g[ps]);
        dfs(ps+1,res,ans);
        return;
    }
    inline int get(int x){
        g[0]=0;
        cnt=0;
        for(register int i=2;i<=sqrt(x);++i){
            if(x%i==0) g[++g[0]]=i;
            while(x%i==0) x/=i;
        }
        if(x!=1) g[++g[0]]=x;
        dfs(1,0,1);
        
        return cnt;
    }
    inline void Modify(int x,int opt){
        for(register int i=1;i<sqrt(x);++i){
            if(x%i==0) num[i]+=opt,num[x/i]+=opt; 
        }
        if((int)((int)sqrt(x)*(int)sqrt(x))==x) num[(int)sqrt(x)]+=opt;
        return;
    }
    int a[MAXN],Ans,Num,vis[MAXN];
    signed main(){
        freopen("coprime.in","r",stdin);
        freopen("coprime.out","w",stdout);
        n=read(),q=read();
        for(register int i=1;i<=n;i++) a[i]=read();
        for(register int i=1;i<=q;i++){
            int x=read();
            vis[x]^=1;
            if(vis[x]==1){
                if(a[x]==1) Ans+=Num;
                else Ans+=(Num-get(a[x]));
                Modify(a[x],1);
                Num++;
            }else{
                if(a[x]==1) Ans-=(Num-1);
                else Ans-=(Num-get(a[x]));
                Modify(a[x],-1);
                Num--;
            }
            printf("%lld
    ",Ans);
        }return 0;
    }
    View Code

    斐波那契

    题意简述

    $T$ 组询问,每次询问 $(F_nmod F_k)mod 10^9+7$ 。$F_i$ 表示斐波那切数列第 $i$ 项。

    $Tleq 5 imes 10^4,n,kleq 10^{18}$ 。

    $solution:$

    考虑对于 $F_k$ 递推得到 $F_n$ 。

    $F_{k-1}=F_1 imes F_{k-1}+F_0 imes F_k,F_k=F_0 imes F_{k-1}+F_1 imes F_k$ 。

    通过 $F_i=F_{i-2}+F_{i-1}$ 可以得到 $F_n=F_{n-k} imes F_{k-1}+F_{n-k+1} imes F_k$ 。

    下面公式省略 $mod f_k$

    则 $$F_n=F_{n-k} imes F_{k-1}+F_{n-k+1} imes F_k\equiv F_{n-k} imes F_{k-1}$$

    对于 $F_{n-k}$ 依然可以迭代,设 $p=[dfrac{n}{k}],q=nmod k$ 。

    $$F_nequiv f_{k-1}^p imes f_q$$

    通过找规律发现 $$F_{k-1}^2+F_{k-1} imes F_k-F_k^2=(-1)^k$$ 

    推出 $$F_{k-1}^2equiv (-1)^k$$

    发现答案与 $p$ 的奇偶有关。

    当 $p$ 为偶数时,$$F_nequiv[(-1)^k]^{frac{p}{2}} imes F_q$$

    当 $p$ 为奇数时,我们发现无法去表达出对 $f_k$ 取模的值,考虑将 $i$ 值补为偶数。

    将斐波那切数列拓展到负域中,$f_{-i}=(-1)^{i+1} imes f_i$ ,所以$$F_nequiv F_{k-1}^{p+1} imes F_{q-k}\equiv  (-1)^{k-q+1} imes F_{k-1}^{p+1} imes F_{k-q}$$

    然后就同 $p$ 为偶数处理即可。

    每次只要用矩阵快速幂快速求出 $F$ 即可。

    时间复杂度 $O(Tlog k)$ 。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define int long long
    #define mod 1000000007
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    struct Matrix{
        int a[3][3];
        void clear(){memset(a,0,sizeof(a));}
    }F,G;
    Matrix operator*(Matrix x1,Matrix x2){
        Matrix x3;x3.clear();
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++)
                for(int k=1;k<=2;k++) x3.a[i][j]+=x1.a[i][k]*x2.a[k][j],x3.a[i][j]%=mod;
        return x3;
    }
    Matrix ksm(Matrix a,int b){
        Matrix ans;ans.clear();
        for(int i=1;i<=2;i++) ans.a[i][i]=1;
        while(b){
            if(b&1) ans=ans*a;
            a=a*a,b>>=1;
        }return ans;
    }
    int Qfib(int ps){
        if(ps==0) return 0;
        if(ps==1) return 1;
        F.clear(),G.clear();
        F.a[1][1]=F.a[1][2]=F.a[2][1]=1;
        G=ksm(F,ps-1);
        return G.a[1][1];
    }
    int Mod(int x){return ((x%mod)+mod)%mod;}
    int T,n,k;
    void solve(){
        n=read(),k=read();
        if(k<=2){printf("0
    ");return;}
        if(n<k){printf("%lld
    ",Qfib(n));return ;}
        int p=n/k,q=n%k;
        if(q==0){printf("%d
    ",0);return;}
        if(p%2==0){
            int opt=((k*(p/2))&1?-1:1);
            if(Qfib(q)==0){printf("%lld
    ",0);return;}
            if(opt==1){printf("%lld
    ",Qfib(q));return;}
            printf("%lld
    ",Mod(Qfib(k)-Qfib(q)));
            return;
        }
        p++;
        int opt=(((k*(p/2)&1))?-1:1)*(((k-q+1)&1)?-1:1);
        if(opt==1){printf("%lld
    ",Qfib(k-q));return;}
        else {printf("%lld
    ",Mod(Qfib(k)-Qfib(k-q)));return;}
        return;
    }
    signed main(){
    //    freopen("make.in","r",stdin);
        freopen("fib.in","r",stdin);
        freopen("fib.out","w",stdout);
        T=read();
        while(T--) solve();
        return 0;
    }
    View Code

    不连续回文串

    题意简述

    给定一个长度为 $n$ 的 $01$ 字符串。

    求出满足位置和字符均对于某条对称轴对称的不连续回文子串。

    答案对 $10^9+7$ 取模。

    $nleq 10^5$ 。

    $solution:$

    先不考虑不连续这个限制,最后可以直接二分加哈希求出。

    如果 $l,r$ 会对于 $x$ 这个位置作贡献,必须满足 $a_l=a_r,2x=l+r$ 。

    直接对于 $0,1$ 分别卷积后快速幂求出对数即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define int long long
    #define mod 1004535809
    #define Mod 1000000007
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=400001;
    int n,m,flip[MAXN],f[MAXN],g[MAXN];
    int ksm(int a,int b,int MOd){
        int ans=1;
        while(b){
            if(b&1) ans*=a,ans%=MOd;
            a*=a,a%=MOd;
            b>>=1;
        }return ans;
    }
    inline void NTT(int *f,int opt){
        for(int i=0;i<n;i++) if(i<flip[i]) swap(f[i],f[flip[i]]);
        for(int p=2;p<=n;p<<=1){
            int len=p>>1,buf=ksm(3,(mod-1)/p,mod);
            if(opt==-1) buf=ksm(buf,mod-2,mod);
            for(int be=0;be<n;be+=p){
                int tmp=1;
                for(int l=be;l<be+len;l++){
                    int t=f[l+len]*tmp;t%=mod;
                    f[len+l]=(f[l]-t+mod)%mod,f[l]=(f[l]+t)%mod;
                    tmp*=buf,tmp%=mod;
                }
            }
        }if(opt==-1){
            int Inv=ksm(n,mod-2,mod);
            for(int i=0;i<n;i++) f[i]*=Inv,f[i]%=mod;
        }return;
    }
    char str[MAXN];
    int len,a[MAXN];
    inline void work(int opt){
        memset(f,0,sizeof(f)),memset(g,0,sizeof(g));
        n=len,m=len;
        for(int i=1;i<=len;i++)
            if(a[i]==opt) f[i]=g[i]=1;
        m+=n;
        for(n=1;n<=m;n<<=1);
        for(int i=0;i<n;i++) flip[i]=(flip[i>>1]>>1)|(i&1?n>>1:0);
        NTT(f,1),NTT(g,1);
        for(int i=0;i<n;i++) f[i]*=g[i],f[i]%=mod;
        NTT(f,-1);
        return;
    }
    int ans[MAXN],Ans,pw[MAXN],Hash1[MAXN],Hash2[MAXN],Cnt;
    inline int hash1(int l,int r){return Hash1[r]-Hash1[l-1]*pw[r-l+1];}
    inline int hash2(int l,int r){return Hash2[l]-Hash2[r+1]*pw[r-l+1];}
    inline int solve(){
        n=len;
        pw[0]=1;for(int i=1;i<=n;i++) pw[i]=pw[i-1]*3;
        for(int i=1;i<=n;i++) Hash1[i]=Hash1[i-1]*3+a[i];
        for(int i=n;i>=1;i--) Hash2[i]=Hash2[i+1]*3+a[i];
        for(int i=1;i<=n;i++){
            int l=0,r=min(i-1,n-i),Maxn=INT_MIN;
            while(l<=r){
                int mid=l+r>>1;
                if(hash1(i-mid,i)==hash2(i,i+mid)){Maxn=max(Maxn,mid);l=mid+1;}
                else r=mid-1;
            }
            Cnt+=Maxn+1;
        }
        for(int i=1;i<n;i++){
            int l=1,r=min(i,n-i),Maxn=0;
            while(l<=r){
                int mid=l+r>>1;
                if(hash1(i-mid+1,i)==hash2(i+1,i+mid)){Maxn=max(Maxn,mid);l=mid+1;}
                else r=mid-1;
            }
            Cnt+=Maxn;
        }return Cnt;
    }
    signed main(){
        freopen("palindrome.in","r",stdin);
        freopen("palindrome.out","w",stdout);
        scanf("%s",str+1);
        len=strlen(str+1);
        for(int i=1;i<=len;i++) a[i]=str[i]-'0';
        work(0);
        for(int i=2;i<=2*len;i++) ans[i]+=f[i],ans[i]%=Mod;
        work(1);
        for(int i=2;i<=2*len;i++) ans[i]+=f[i],ans[i]%=Mod;
        int Inv=ksm(2,Mod-2,Mod);
        for(int i=2;i<=2*len;i++){
            if(i%2==0){
                Ans+=ksm(2,((ans[i]+1)*Inv)%Mod,Mod);
                Ans--;Ans=((Ans%Mod)+Mod)%Mod;
            }else{
                Ans+=ksm(2,(ans[i]*Inv)%Mod,Mod);
                Ans--;Ans=((Ans%Mod)+Mod)%Mod;
            }
        }printf("%lld
    ",(((Ans-solve())%Mod)+Mod)%Mod);return 0;
    }
    View Code
  • 相关阅读:
    ORACLE DBA的职责
    oracle开发常用LOV
    Oracle Patch 版本的查询
    指定二次分配为主要分配
    系统日期格式引起的错误:出生日期不能为将来日期
    分享一个帮助你检测网站颜色对比度的在线web工具 checkmycolours
    最常用的CURL命令大全
    超棒的javascript移动触摸设备开发类库 QUOjs
    分享一个超炫HTML5开发的jQuery进度条插件 percentageloader
    纯CSS实现的3D简洁按钮设计
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/11272125.html
Copyright © 2011-2022 走看看