• 式神守护


    式神守护

    n,q 2e5  m 20


    solution

    好题

    ?pts dp。令f[i][j]表示前i个数组成j的方案数。f[i+1][j+a[k]]=f[i][j+a[k]]+f[i][j].O(q*n*m*m);

    40pts 线段树维护答案 效率O(nlogn*m^2)

    100pts 考虑分治

    假设我正在处理(l,r)

    把跨过mid的询问提出来,剩下的分治处理。

    把l~mid,mid~r分别做dp,然后对于每个询问再O(m)把两端dp值合起来

    效率O(nlogn+qm)

    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 200005
    #define ll long long
    #define mod 1000000007
    using namespace std;
    int n,m,a[maxn],Q,ans[maxn];
    ll f[maxn][22],g[maxn][22];
    struct node{
        int l,r,id;
    }q[maxn],s[maxn];
    void solve(int l,int r,int ql,int qr){
        if(ql>qr)return;
        if(l==r){
            for(int i=ql;i<=qr;i++){
                ans[q[i].id]=1;
            }return;
        }
        int mid=l+r>>1;
        int t1=0,t2,t3;
         
        for(int i=ql;i<=qr;i++)if(q[i].r<=mid)s[++t1]=q[i];
        t2=t1;
        for(int i=ql;i<=qr;i++)if(q[i].l<=mid&&q[i].r>mid)s[++t2]=q[i];
        t3=t2;
        for(int i=ql;i<=qr;i++)if(q[i].l>mid)s[++t3]=q[i];
        for(int i=1,j=ql;i<=t3;i++,j++)q[j]=s[i];
        solve(l,mid,ql,ql+t1-1);solve(mid+1,r,ql+t2,qr);
        for(int i=l;i<=mid+1;i++)
            for(int j=0;j<m;j++)f[i][j]=0;
        for(int i=mid;i<=r;i++)
            for(int j=0;j<m;j++)g[i][j]=0;
        f[mid+1][0]=1;g[mid][0]=1;
         
        for(int i=mid+1;i>=l;i--){
            for(int j=0;j<m;j++){
                f[i-1][(j+a[i-1])%m]=(f[i-1][(j+a[i-1])%m]+f[i][j])%mod;
            }
            for(int j=0;j<m;j++)f[i-1][j]+=f[i][j],f[i-1][j]%=mod;
        }
        for(int i=mid;i<=r;i++){
            for(int j=0;j<m;j++){
                g[i+1][(j+a[i+1])%m]=(g[i+1][(j+a[i+1])%m]+g[i][j])%mod;
            }
            for(int j=0;j<m;j++)g[i+1][j]+=g[i][j],g[i+1][j]%=mod;
        }
        for(int i=ql+t1;i<ql+t2;i++){
            int L=q[i].l,R=q[i].r;ll Ans=0;
            for(int j=0;j<m;j++){
                int t=m-j;if(t>=m)t-=m;
                Ans=Ans+f[L][j]*g[R][t]%mod;Ans%=mod;
            }
            ans[q[i].id]=Ans;
        }
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            a[i]%=mod;
        }
        cin>>Q;
        for(int i=1;i<=Q;i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }
        solve(1,n,1,Q);
        for(int i=1;i<=Q;i++)printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    编程总结3
    编程总结2
    编程总结1
    对我影响最深的老师
    自我介绍
    BFC 规则及解决的问题?
    简述 CSS 精灵图原理,及优缺点?
    等高布局、圣杯布局、双飞翼布局的实现原理
    CSS 基本选择器有哪些?
    CSS 引入方式有哪些?
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358787.html
Copyright © 2020-2023  润新知