• 2018.11.01-dtoj-4020: 式神守护(yukari)——(类)整体二分


    题目描述:

    紫妈有n 个隙间排成一列,每个隙间都有一个权值 val 。
    她可以选出某些隙间来召唤式神:一组隙间能成功召唤式神当且仅当他们的权值和为m
    的倍数。(可以是0 倍)
    现在紫妈试图召唤Q次式神,每次给出一个 l和r ,她试图在第 l到r 个隙间中召唤式神,
    她会选择其中一些隙间(不一定需要连续的一些)召唤式神。她想知道,有多少种方案可以
    成功召唤式神。

    输入:

    第一行两个数,n 和m。
    第二行n 个数,表示i val 。
    第三行一个数,表示Q。
    下面Q行,每行两个数,表示i i l和r 。

    输出:

    Q行,每行一个数,表示方案数,方案数mod (109  7 )输出。

    数据范围:

    n,q≤2*105,m≤20

    算法标签:(类整体二分),分治

    思路:

    把问题分治,每次只管理跨过区间的情况,代码看起来很暴力,但是仔细一算时间发现的确优秀。

    jzy的整体二分||分治初体验

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=2e5+5,p=1e9+7;
    struct npode{int l,r,ans;}t[N];
    int n,m,q,res[N],f[N][22],g[N][22],a[N],tmp[N],val[N],b[N];
    il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;}
    il int mu(int x){if(x>=p)return x-p;return x;}
    il void solve(int l,int r,int L,int R){
        int mid=(l+r)>>1;
        if(l==r){
            for(int i=L;i<=R;i++){
                t[a[i]].ans=(val[l]==0?2:1);
            }
            return;
        }
        for(int j=1;j<m;j++)f[mid+1][j]=0;
        f[mid+1][0]=1;
        for(int i=mid;i>=l;i--){
            for(int j=0;j<m;j++){
                int now=(j-val[i]+m)%m;
                f[i][j]=mu(f[i+1][now]+f[i+1][j]);
            }
        }
        for(int j=1;j<m;j++)g[mid][j]=0;
        g[mid][0]=1;
        for(int i=mid+1;i<=r;i++){
            for(int j=0;j<m;j++){
                int now=(j-val[i]+m)%m;
                g[i][j]=mu(g[i-1][now]+g[i-1][j]);
            }
        }
        int tot1=L-1,tot2=R+1;
        for(int i=L;i<=R;i++){
            if(t[a[i]].r<=mid)b[++tot1]=a[i];
            else if(t[a[i]].l>mid)b[--tot2]=a[i];
            else{
                t[a[i]].ans=mu(t[a[i]].ans+(LL)f[t[a[i]].l][0]*(LL)g[t[a[i]].r][0]%p);
                for(int j=1;j<m;j++){
                    t[a[i]].ans=mu(t[a[i]].ans+(LL)f[t[a[i]].l][j]*(LL)g[t[a[i]].r][m-j]%p);
                }
            }
        }
        for(int i=L;i<=tot1;i++)a[i]=b[i];
        for(int i=tot2;i<=R;i++)a[i]=b[i];
        if(tot1>=L)solve(l,mid,L,tot1);
        if(tot2<=R)solve(mid+1,r,tot2,R);
    }
    int main()
    {
        n=read();m=read();for(int i=1;i<=n;i++)val[i]=read()%m;
        q=read();for(int i=1;i<=q;i++)t[i].l=read(),t[i].r=read();
        for(int i=1;i<=q;i++)a[i]=i;solve(1,n,1,q);
        for(int i=1;i<=q;i++)printf("%d
    ",t[i].ans);
      return 0;
    }
    View Code
  • 相关阅读:
    Extension Method[下篇]
    Extension Method[上篇]
    科大讯飞和Tizen-TTS语音合成引擎
    c语言中格式化输出函数的研究
    五脏积毒的表现 脸上长痘位置看你健康情况
    Android API Level与sdk版本对照表
    ffmpeg ffprobe ffplay
    sqlite 修改表名,合并数据库(文件)
    Spring配置文件的加载,及装载多个beans.xml文件
    ffmpeg 的tutorial
  • 原文地址:https://www.cnblogs.com/Jessie-/p/9889603.html
Copyright © 2020-2023  润新知