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
  • 相关阅读:
    hdu 5119 Happy Matt Friends
    hdu 5128 The E-pang Palace
    hdu 5131 Song Jiang's rank list
    hdu 5135 Little Zu Chongzhi's Triangles
    hdu 5137 How Many Maos Does the Guanxi Worth
    hdu 5122 K.Bro Sorting
    Human Gene Functions
    Palindrome(最长公共子序列)
    A Simple problem
    Alignment ( 最长上升(下降)子序列 )
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8516438.html
Copyright © 2011-2022 走看看