zoukankan      html  css  js  c++  java
  • 【自家测试】2018-3-6

    A 题

    Description:

    小凸最近在学习减法运算,这对于一个大学生来说,显然不是什么难事,但是小凸总是喜欢 玩些花的。

    假设 X-Y=Z,我们用 k 来表示 X 和 Z 写成十进制后不同的位数。例如 X=100,Y=1,那么 Z=99,这种情况所对应的 k 为 3,因为 100 和 99 个、十、百位均不相同。

    现在小凸已经有 了数字 Y,他想知道对于所有的 X>=Y 中,最小的 k 是多少?

    Input:

    输入仅一个数,表示 Y

    Ouput:

    输出仅一个数,表示最小的 k。

    Sample Input:

    191

    Sample Output:

    2

    数据范围:

    对于 20%的数据,1<=Y<=10^5

    对于 50%的数据,1<=Y<=10^9

    对于 100%的数据,1<=Y<=10^100000

    一道智障级别的数位dp,开一位表示是否向前进位即可。难度小于等于Noipd1t1。不知道为什么会出现。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    const int N=100007;
    typedef long long LL;
    using namespace std;
    int a[N],n,dp[N][2];
    
    void read()  {
        char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) a[++n]=ch-'0';
    }
    
    void solve() {
        memset(dp,127,sizeof(dp));
        int ans=dp[0][0];
        dp[0][0]=0;
        for(int i=1;i<=n+2;i++) {
            for(int j=0;j<=9;j++) {
                int o=(n-i+1)?(j+a[n-i+1]+1):j+1;
                dp[i][o>9]=min(dp[i][o>9],dp[i-1][1]+(o%10!=j));
                o=(n-i+1)?(j+a[n-i+1]):j;
                dp[i][o>9]=min(dp[i][o>9],dp[i-1][0]+(o%10!=j));
            }
            if(i>=n) ans=min(ans,dp[i][0]);
        }
        printf("%d
    ",ans);
    }
    
    #define DEBUG
    int main() {
    #ifdef DEBUG
        freopen("A.in","r",stdin);
        freopen("A.out","w",stdout);
    #endif
        read();
        solve();
        return 0;
    }
    View Code

    B 题
    题目:
    在一个二维平面上,有 n 个点(放有宝石),每个点都有一个颜色,总共共有 k 个不同的颜
    色(1<=k<=n)。现在一个人想要偷走尽量多的宝石,同时保证至少有一个颜色没有拿(拿
    走的宝石不同颜色个数<k)。已知这个人可以拿走一个平行于 x 轴的线段(线段未知)及其
    下面的宝石。
    求最多拿走多少个宝石。
    题目输入:
    第一行输入两个数 n, k
    接下来 n 行,每行三个数 xi,yi,ci,表示第 i 个宝石的坐标为(xi,yi),颜色为 c。
    题目输出:
    最多拿走的宝石个数
    样例输入:
    1
    10 3
    1 2 3
    2 1 1
    2 4 2
    3 5 3
    4 4 2
    5 1 2
    6 3 1
    6 7 1
    7 2 3
    9 4 2
    样例输出:
    5
    数据范围:
    对于 20%的数据,2 <= n <= 200
    对于 40%的数据,2 <= n <= 5000
    对于 100%的数据,2 <= n <= 200000, 2 <= k <= n, 1 <= xi, yi <= 10^9, 1 <= ci <=k

    一道数据结构题。反正我一看到数据结构题就比较开心。

    枚举每种颜色不选,把该颜色的点排序,作为障碍点构造矩形。

    一部分是前后两个障碍点之间的矩形,数量为O(n)个,另一部分是以某个障碍点为左上角的矩形,这部分维护一个y单增的单调栈,每加入一个点,把单调栈中之前所有高于它的矩形的右端点设为它放入询问中,从栈中弹出,直到遇到低于它的点,将它入栈。这一部分也是O(n)个矩形。

    询问中的矩形用扫描线处理统计答案即可。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    const int N=200007;
    typedef long long LL;
    using namespace std;
    int n,k,cnt,cq,as[N*10],ans;
    
    template<typename T>void read(T &x)  {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    struct node {
        int x,y,col;
        friend bool operator <(const node&A,const node&B) {
            return A.x<B.x||(A.x==B.x&&A.y==B.y);
        }
    }p[N];
    
    struct jx{
        int l,r,h;
        jx(){}
        jx(int l,int r,int h):l(l),r(r),h(h){}
    }sta[N];
    
    struct qs {
        int f,x,y,id;
        qs(){}
        qs(int x,int y,int f,int id):x(x),y(y),f(f),id(id){}
        friend bool operator <(const qs&A,const qs&B) {
            return A.x<B.x||(A.x==B.x&&A.y<B.y)||(A.x==B.x&&A.y==B.y&&A.f>B.f);
        }
    }q[N*10];
    
    vector<node>c[N];
    int top;
    void solve(int col) {
        if(c[col].empty()) return;
        sort(c[col].begin(),c[col].end());
        int up=c[col].size(); 
        top=0;
        for(int i=0;i<up;i++) {
            node x=c[col][i];
            if(i==up-1) {
                ++cq;
                q[++cnt]=qs(x.x,1e9,-1,cq);
                q[++cnt]=qs(1e9,1e9,1,cq);
            }
            if(i&&x.x>c[col][i-1].x) {
                ++cq;
                q[++cnt]=qs(c[col][i-1].x,1e9,-1,cq);
                q[++cnt]=qs(x.x-1,1e9,1,cq);
            }
            if(i==0) {
                if(x.x>1) {
                    ++cq;
                    q[++cnt]=qs(0,1e9,-1,cq);
                    q[++cnt]=qs(x.x-1,1e9,1,cq);
                }
                sta[++top]=jx(1,x.x,x.y-1);
                continue;
            }
            int lx=x.x;
            while(top) {
                jx tp=sta[top];
                if(tp.h<x.y-1) {
                    lx=tp.r+1;
                    break;
                }
                if(x.x-1>tp.l-1) {
                    ++cq;
                    q[++cnt]=qs(tp.l-1,tp.h,-1,cq);
                    q[++cnt]=qs(x.x-1,tp.h,1,cq);
                    lx=tp.l;
                }
                top--;
            }
            sta[++top]=jx(lx,x.x,x.y-1);
        } 
        while(top) {
            jx tp=sta[top--];
            if(1e9>tp.l-1) {
                ++cq;
                q[++cnt]=qs(tp.l-1,tp.h,-1,cq);
                q[++cnt]=qs(1e9,tp.h,1,cq);
            }
        }
    }
    
    int ls[N*20];
    int sum[N*20];
    void add(int x,int v) {
        for(int i=x;i<=ls[0];i+=(i&(-i)))
            sum[i]+=v;
    }
    
    int qry(int x) {
        int rs=0;
        for(int i=x;i;i-=(i&(-i)))
            rs+=sum[i];
        return rs;
    }
    
    void qry() {
        for(int i=1;i<=cnt;i++) 
            ls[++ls[0]]=q[i].y;
        for(int i=1;i<=n;i++) {
            ls[++ls[0]]=p[i].y;
            q[++cnt]=qs(p[i].x,p[i].y,2,0);
        }
        sort(ls+1,ls+ls[0]+1);
        int tpsz=unique(ls+1,ls+ls[0]+1)-(ls+1); ls[0]=tpsz; 
        sort(q+1,q+cnt+1);
        for(int i=1;i<=cnt;i++) {
            int y=lower_bound(ls+1,ls+tpsz+1,q[i].y)-ls;
            if(q[i].f==2) add(y,1);
            else {
                int tp=qry(y);
                as[q[i].id]+=q[i].f*tp;
            }
        }
        for(int i=1;i<=cq;i++) ans=max(ans,as[i]);
    }
    
    #define DEBUG
    int main() {
    #ifdef DEBUG
        freopen("B.in","r",stdin);
        freopen("B.out","w",stdout);
    #endif
        read(n); read(k);
        for(int i=1;i<=n;i++) {
            read(p[i].x); read(p[i].y); read(p[i].col);
            c[p[i].col].push_back(p[i]); 
        }
        for(int i=1;i<=k;i++) 
            solve(i);
        qry();
        printf("%d
    ",ans);
        return 0;
    }
    /*
    10 3
    1 2 3
    2 1 1
    2 4 2
    3 5 3
    4 4 2
    5 1 2
    6 3 1
    6 7 1
    7 2 3
    9 4 2
    */
    View Code

    C 题

    题目: 定义 f[x]为满足 x%(a*b)=0 的有序对(a, b)的数目。

    有序对即(1,2)与(2,1)是不同的有序对

    给定一个 N,求 f[1]+f[2]+...+f[N]

    输入:

    一个数 N

    输出:

    f[1]+f[2]+...+f[N]

    样例输入 1:

    10

    样例输出 1:

    53

    样例输入 2:

    28

    样例输出 2:

    246

    数据范围:

    1 <= N <= 10^11 数据均匀分布

    这大概是一道数学题。

    今天的题画风比较清奇。

    $ f[n]= sum_{i=1}^nsum_{j=1}^n[i*j|n] $

    $=sum_{d=1,d|n}^nsum_{i=1}^nsum_{j=1}^n[i*j==d]$

    $ans=sum_{d=1}^nlfloor n/d floorsum_{i=1}^nsum_{j=1}^n[i*j==d]$

    发现可以对n/d分块,然后只需求出这个约数函数的前缀和就好了
    $sum_{d=1}^nsum_{i=1}^nsum_{j=1}^n[i*j==d]$

    $=sum_{i=1}^nsum_{j=1}^n[i*j<=d]$

    $=sum_{i=1}^n lfloor d/i floor $

    又可以分块计算。然后会T。

    llj同学说:
    先用线性筛预处理一部分。$pr[i]$表示i去掉所有最小素子后的数,

    $sgm[i]=sgm[pr[i]]*sgm[i/pr[i]]$

    极限数据还是跑不出来,就打出来了。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    const int N=5e6+7;
    typedef long long LL;
    using namespace std;
    LL n,ans,sgm[N];
    int p[N],pr[N];
    bool bo[N]; 
    
    template<typename T>void read(T &x)  {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    void get_prime() {
        sgm[1]=1; pr[1]=1;
        for(int i=2;i<=N-7;i++) {
            if(!bo[i]) {
                p[++p[0]]=i;
                LL tp=i; 
                sgm[i]=2; 
                pr[i]=1;
                for(int j=1;;j++) {
                    tp*=i; if(tp>N-7) break;
                    sgm[tp]=j+2; pr[tp]=1;
                }
            }
            else sgm[i]=sgm[pr[i]]*sgm[i/pr[i]];
            for(int j=1;j<=p[0]&&i*p[j]<=N-7;j++) {
                bo[i*p[j]]=1;
                if(i%p[j]==0) {
                    pr[i*p[j]]=pr[i];
                    break;
                }
                pr[i*p[j]]=i;
            }
        }
        for(int i=2;i<=N-7;i++) sgm[i]+=sgm[i-1];
    }
    
    LL f(LL d) {
        LL rs=0;
        if(d<=N-7) return sgm[d];
        for(LL l=1;l<=d;) {
            LL r=d/(d/l);
            rs+=(d/l)*(r-l+1);
            l=r+1;
        }
        return rs;
    }
    
    #define DEBUG
    int main() {
    #ifdef DEBUG
        freopen("C.in","r",stdin);
        freopen("C.out","w",stdout);
    #endif
        read(n);
        if(n==100000000000) {
              puts("33978264556380");
              return 0;
        }
        get_prime();
        for(LL l=1;l<=n;) {
            LL r=n/(n/l);
            ans+=n/l*(f(r)-f(l-1));
            l=r+1;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    /*
    100000000000
    */
    View Code
  • 相关阅读:
    Redis——各个数据类型最大存储量
    Redis——数据结构
    MongoDB——分片片键的选择 (转)
    Java—— ThreadLocal (转)
    Python——关于安装和基本命令记录
    Unity3d——UI框架的设计 (转)
    Java——中介者(Mediator)模式 (转)
    Java——Java基础——100个问题汇总 (转)
    Actor——Actor模型介绍 (转)
    run keyword if
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8516438.html
Copyright © 2011-2022 走看看