• 【JZOJ4744】【NOIP2016提高A组模拟9.2】同余


    题目描述

    题目描述

    输入

    输入

    输出

    输出

    样例输入

    5 2
    1 5 2 3 7
    1 3 2 1
    2 5 3 0

    样例输出

    2
    1

    数据范围

    数据范围

    解法

    题目允许离线,且没有修改操作。
    考虑把一个询问拆分成两个形如”a b c”的询问,表示1~a这些数中mod b余c有多少个。
    使用扫描线,把元素加入一个桶tong里面去。①
    对于一个询问”a b c”,那么答案就是tong[c+kb] (k|c+kb<=10000)。
    当b>=100时,询问答案最多耗时O(100);
    当b<100时,询问答案最多耗时O(10000),考虑到b比较小,所以在①处额外维护一个二维桶xt[][],xt[i][j]表示模数为i,余数为j的个数有多少个。
    于是询问变成O(1)。
    总的时间复杂度为O(n*maxa^0.5)。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    #define sqr(x) ((x)*(x))
    #define ln(x,y) int(log(x)/log(y))
    using namespace std;
    const char* fin="aP3.in";
    const char* fout="aP3.out";
    const int inf=0x7fffffff;
    const int maxn=100007,maxa=10007,mina=107,maxv=maxn*2;
    int n,m,i,j,k,l,o,tot,maxx,minx;
    int a[maxn];
    int ans[maxn][2];
    int tong[maxa],xt[mina][mina];
    struct visit{
        int en,p,q,id,tp;
        void init(int a,int b,int c,int d,int e){
            en=a;p=b;q=c;id=d;tp=e;
        }
        void work(){
            int i,j,k;
            if (p>minx) for (j=q;j<=maxx;j+=p) ans[id][tp]+=tong[j];
            else ans[id][tp]=xt[p][q];
        }
    }b[maxv];
    bool cmp(visit i,visit j){
        return i.en<j.en;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++){
            scanf("%d",&a[i]);
            maxx=max(maxx,a[i]);
        }
        maxx=10000;
        minx=int(sqrt(maxx));
        for (i=1;i<=m;i++){
            scanf("%d%d%d%d",&j,&k,&l,&o);
            if (j>1) b[++tot].init(j-1,l,o,i,0);
            b[++tot].init(k,l,o,i,1);
        }
        sort(b+1,b+tot+1,cmp);
        k=1;
        for (i=1;i<=n;i++){
            tong[a[i]]++;
            for (j=1;j<=minx;j++) xt[j][a[i]%j]++;
            while (k<=tot && b[k].en==i) b[k++].work();
        }
        for (i=1;i<=m;i++){
            j=ans[i][1]-ans[i][0];
            printf("%d
    ",j);
        }
        return 0;
    }

    启发

    本题关键有两处,①是询问离线且没有修改,②是maxa<=10000;
    ①使得问题可以转化为简单的子问题;
    ②使得可以分类讨论来进行优化。
    日后额外注意形如上述性质。

  • 相关阅读:
    oracle 自定义字符串分割函数split()
    oracle 创建md5函数
    eclipse 纯java项目如果导入外部jar包?
    tomcat server.xml标签功能详解
    oracle 根据汉字生成首字母简拼(助记码)
    IDEA的注解自动成了中文,怎么恢复正常
    @TransactionalEventListener 之Spring的事务监听器
    Git fork常用方法
    Mapstruct源码解析 框架实现原理
    Git提交到其他分支了,需要把其他分支上的部分commit迁回cherrypick
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714911.html
Copyright © 2020-2023  润新知