zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 81 (Rated for Div. 2)

    A. Display The Number (CF 1295 A)

    题目大意

    (n)个火柴棒,问摆出的最大数字是多少?摆出每个数字所需要的火柴棒参照红绿灯。
    红绿灯

    解题思路

    贪心即可。不断放(1),最后如果剩下一个火柴棒则最高位变成(7)

    神奇的代码
    #include <bits/stdc++.h>
    #define MIN(a,b) ((((a)<(b)?(a):(b))))
    #define MAX(a,b) ((((a)>(b)?(a):(b))))
    #define ABS(a) ((((a)>0?(a):-(a))))
    using namespace std;
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<PII> VPII;
    typedef vector<LL> VL;
    typedef pair<LL,LL> PLL;
    typedef vector<PLL> VPLL;
    
    template <typename T>
    void read(T &x) {
        int s = 0, c = getchar();
        x = 0;
        while (isspace(c)) c = getchar();
        if (c == 45) s = 1, c = getchar();
        while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        if (s) x = -x;
    }
    
    template <typename T>
    void write(T x, char c = ' ') {
        int b[40], l = 0;
        if (x < 0) putchar(45), x = -x;
        while (x > 0) b[l++] = x % 10, x /= 10;
        if (!l) putchar(48);
        while (l) putchar(b[--l] | 48);
        putchar(c);
    }
    
    int main(void) {
        int kase; read(kase);
        for (int i = 1; i <= kase; i++) {
            int n;
            read(n);
            int a[100500]={0};
            int cnt=-1;
            while(n>=2){
                a[++cnt]=1;
                n-=2;
            }
            if (n==1) a[cnt]=7;
            for(int i=cnt;i>=0;--i) putchar(a[i]+'0');
            puts("");
        }
        return 0;
    }
    


    B. Infinite Prefixes (CF 1295 B)

    题目大意

    给定一个(01)(s),串(t)由串(s)不断重复得到,是无限长的。定义函数(f(x)=cnt_0(x)-cnt_1(x)),其中(cnt_0(x))表示串(t)第一位到第(x)(0)的个数,(cnt_1)同理。给定一个数(x),问有多少个(i)使得(f(i)=x),无限则输出(-1)

    解题思路

    由于(s)串是(t)串不断重复得到,(x=f(j)=k*f(n)+f(i)),其中(k=lfloor frac{j}{n} floor ,i=j\%n),%是求余,且(f(0)=0),所以(k=dfrac{x-f(i)}{f(n)}),对于每一个(i in [1,n]),我们只要判断是否((x-f(i))*f(n)>0)((x-f(i))\%f(n)==0)即可。当(f(n))(0)(f(1))(f(n))中存在等于(x)的则答案无限。注意如果(x=0)的话还要加上一开始的空串。

    神奇的代码
    #include <bits/stdc++.h>
    #define MIN(a,b) ((((a)<(b)?(a):(b))))
    #define MAX(a,b) ((((a)>(b)?(a):(b))))
    #define ABS(a) ((((a)>0?(a):-(a))))
    using namespace std;
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<PII> VPII;
    typedef vector<LL> VL;
    typedef pair<LL,LL> PLL;
    typedef vector<PLL> VPLL;
    
    template <typename T>
    void read(T &x) {
        int s = 0, c = getchar();
        x = 0;
        while (isspace(c)) c = getchar();
        if (c == 45) s = 1, c = getchar();
        while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        if (s) x = -x;
    }
    
    template <typename T>
    void write(T x, char c = ' ') {
        int b[40], l = 0;
        if (x < 0) putchar(45), x = -x;
        while (x > 0) b[l++] = x % 10, x /= 10;
        if (!l) putchar(48);
        while (l) putchar(b[--l] | 48);
        putchar(c);
    }
    
    int main(void) {
        int kase; read(kase);
        for (int i = 1; i <= kase; i++) {
            int n;
            LL x;
            read(n);
            read(x);
            char s[n]={0};
            LL sum[n]={0};
            scanf("%s",s);
            sum[0]=(s[0]=='0')?1:-1;
            bool qwq=sum[0]==x?true:false;
            for(int i=1;i<n;++i) {
                sum[i]=sum[i-1]+((s[i]=='0')?1:-1);
                if (sum[i]==x) qwq=true;
            }
            if (sum[n-1]==0&&qwq) {puts("-1"); continue;}
            else if (sum[n-1]==0&&!qwq) {puts("0"); continue;}
            if (x*sum[n-1]<0&&!qwq) {puts("0"); continue;}
            LL ans=0;
            for(int i=0;i<n;++i){
                if ((x-sum[i])*sum[n-1]<0) continue;
                if ((x-sum[i])%sum[n-1]==0) ans++;
            }
            if (x==0) ++ans;
            write(ans,'
    ');
        }
        return 0;
    }
    


    C. Obtain The String (CF 1295 C)

    题目大意

    给定两个串(s,t),构造一个串(z)等于(t),每次取(s)的子串加到(z)串的最后,问最少取多少次(s)的子串。子串是指去掉(s)串任意个字母,在不改变剩下字母的相对位置得到的串。无法构造输出(-1)

    解题思路

    (set)储存(s)串中每个字母的位置,记录当前处理的串(s)的位置,模拟就好了。当(t)串有(s)串中不存在的字母则不可构造。

    神奇的代码
    #include <bits/stdc++.h>
    #define MIN(a,b) ((((a)<(b)?(a):(b))))
    #define MAX(a,b) ((((a)>(b)?(a):(b))))
    #define ABS(a) ((((a)>0?(a):-(a))))
    using namespace std;
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<PII> VPII;
    typedef vector<LL> VL;
    typedef pair<LL,LL> PLL;
    typedef vector<PLL> VPLL;
    
    template <typename T>
    void read(T &x) {
        int s = 0, c = getchar();
        x = 0;
        while (isspace(c)) c = getchar();
        if (c == 45) s = 1, c = getchar();
        while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        if (s) x = -x;
    }
    
    template <typename T>
    void write(T x, char c = ' ') {
        int b[40], l = 0;
        if (x < 0) putchar(45), x = -x;
        while (x > 0) b[l++] = x % 10, x /= 10;
        if (!l) putchar(48);
        while (l) putchar(b[--l] | 48);
        putchar(c);
    }
    
    const int N=1e5+8;
    
    char s[N],t[N];
    
    int main(void) {
        int kase; read(kase);
        for (int i = 1; i <= kase; i++) {
            set<int> pos[26];
            scanf("%s%s",s,t);
            int ls=strlen(s);
            bool sign[27]={0};
            for(int i=0;i<ls;++i) pos[s[i]-'a'].insert(i),sign[s[i]-'a']=1;
            int ans=1,cur=-1;
            int lt=strlen(t);
            bool qwq=true;
            for(int i=0;i<lt;++i){
                int x=t[i]-'a';
                if (sign[x]==false) {qwq=false; break;}
                auto a=pos[x].upper_bound(cur);
                if (a==pos[x].end()){
                    ans++;
                    cur=(*pos[x].begin());
                }else cur=*a;
            }
            if (qwq) write(ans,'
    ');
            else puts("-1");
        }
        return 0;
    }
    


    D. Same GCDs (CF 1295 D)

    题目大意

    给定(a,m),求(sumlimits_{x=0}^{m-1}[gcd(a,m)=gcd(a+x,m)])

    解题思路

    (gcd(a,m)=n),则(a=k_1 imes n,m=k_2 imes n),若(gcd(a,m)=gcd(a+x,m)),则(a+x=k_1 imes n+x=k_3 imes n),且(gcd(k_3,k_2)=1),即(k_3)(k_2)互质,其中(k_1 leq k_3 leq lfloor dfrac{a+m-1}{x} floor)。那问题就转化成给定一个数(m),求区间([a,b])有多少个数与(m)互质,容斥即可。
    当然(sumlimits_{i=1}^{a}[gcd(i,m)=1]=sumlimits_{d|m}mu(d) imes frac{a}{d})莫比乌斯或许也可以

    神奇的代码
    #include <bits/stdc++.h>
    #define MIN(a,b) ((((a)<(b)?(a):(b))))
    #define MAX(a,b) ((((a)>(b)?(a):(b))))
    #define ABS(a) ((((a)>0?(a):-(a))))
    using namespace std;
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<PII> VPII;
    typedef vector<LL> VL;
    typedef pair<LL,LL> PLL;
    typedef vector<PLL> VPLL;
    
    template <typename T>
    void read(T &x) {
        int s = 0, c = getchar();
        x = 0;
        while (isspace(c)) c = getchar();
        if (c == 45) s = 1, c = getchar();
        while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        if (s) x = -x;
    }
    
    template <typename T>
    void write(T x, char c = ' ') {
        int b[40], l = 0;
        if (x < 0) putchar(45), x = -x;
        while (x > 0) b[l++] = x % 10, x /= 10;
        if (!l) putchar(48);
        while (l) putchar(b[--l] | 48);
        putchar(c);
    }
    
    vector<LL> prim;
    
    LL a,m;
    
    void divide(LL x){
        prim.clear();
        int qwq=sqrt(x);
        for(int i=2;i<=qwq;++i)
            if (x%i==0){
                prim.push_back(i);
                while(x%i==0) x/=i;
            }
        if (x>1) prim.push_back(x);
    }
    
    LL solve(LL x){
        vector<LL> que;
        que.push_back(-1);
        for(size_t i=0;i<prim.size();++i){
            int k=que.size();
            for(int j=0;j<k;++j)
                que.push_back(prim[i]*que[j]*(-1));   
        }
        LL ans=0;
        for(size_t i=1;i<que.size();++i)
            ans+=x/que[i];
        return x-ans;
    }
    
    int main(void) {
        int kase; read(kase);
        for (int i = 1; i <= kase; i++) {
            read(a);
            read(m);
            LL x=__gcd(a,m);
            LL u=(a+m-1)/x;
            a/=x;
            m/=x;
            divide(m);
            LL ans=solve(u)-solve(a-1);
            write(ans,'
    ');
        }
        return 0;
    }
    

    ~~讲个笑话我内存0 B~~

    E. Permutation Separation (CF 1295 E)

    题目大意

    给定一个排列(p),和一个数组(a)表示这个排列的每个位置的能量值,要求从中间某个位置把排列分成左右两段,然后把左边的一些数移动到右边,右边的一些数移动到左边,使得左边的所有值小于右边的所有值。某个值移动的代价为该位置的能量值。求满足条件所需要的最小能量值。注意,如果有一边没有数,我们也认为这满足了上述的条件(前提假则整个命题为真嘛)。

    解题思路

    我们首先发现,如果左边一段的数的个数是确定的,假设是(k),则最终左边的数一定是(1)~(k),右边的数一定是(k+1)~(n),那么我们先枚举左边一段的数的个数(k),然后再枚举分割点(i)(表示第(i)个数的右边分割),再计算需要的能量值(ans=sumlimits_{jleq i且q_j>k}a_j+sumlimits_{j>i且q_jleq k}a_j),时间复杂度(O(n^3))

    但我们注意到分割点移动的时候,只有分割点右边一个数对答案的贡献改变,于是可以(O(1))更新答案,时间复杂度(O(n^2))

    仔细分析可以发现,当(k)增加时,只有一个数,即(k+1)的归宿才从右边移动到左边,其他数都不变,那我们考虑这个数的归宿改变对答案的影响,可以发现,对于分割点在它左边的答案要增加它的能量值(a_{k+1}),以让它从右边移动到左边,而分割点在它右边的答案要减去它的能量值(a_{k+1}),以消除原来让它从左边移动到右边的所需要的能量。区间修改,用线段树维护答案即可。时间复杂度(O(nlog_{2}n))

    神奇的代码
    #include <bits/stdc++.h>
    #define MIN(a,b) ((((a)<(b)?(a):(b))))
    #define MAX(a,b) ((((a)>(b)?(a):(b))))
    #define ABS(a) ((((a)>0?(a):-(a))))
    using namespace std;
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<PII> VPII;
    typedef vector<LL> VL;
    typedef pair<LL,LL> PLL;
    typedef vector<PLL> VPLL;
    
    template <typename T>
    void read(T &x) {
        int s = 0, c = getchar();
        x = 0;
        while (isspace(c)) c = getchar();
        if (c == 45) s = 1, c = getchar();
        while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
        if (s) x = -x;
    }
    
    template <typename T>
    void write(T x, char c = ' ') {
        int b[40], l = 0;
        if (x < 0) putchar(45), x = -x;
        while (x > 0) b[l++] = x % 10, x /= 10;
        if (!l) putchar(48);
        while (l) putchar(b[--l] | 48);
        putchar(c);
    }
    
    const int N=2e5+8;
    
    struct Segment_Tree{
        #define lson root<<1
        #define rson root<<1|1
    
        LL mark[4*N],minn[4*N];
    
        void build(int root,int l,int r,LL *sum){
            if (l==r){
                minn[root]=sum[l];
                mark[root]=0;
                return;
            }
            int mid=(l+r)>>1;
            build(lson,l,mid,sum);
            build(rson,mid+1,r,sum);
            minn[root]=min(minn[lson],minn[rson]);
            mark[root]=0;
        }
    
        void pushdown(int root){
            mark[lson]+=mark[root];
            mark[rson]+=mark[root];
            minn[lson]+=mark[root];
            minn[rson]+=mark[root];
            mark[root]=0;
        }
    
        void updata(int root,int l,int r,int ll,int rr,LL x){
            if (ll>rr) return;
            if (ll<=l&&r<=rr){
                minn[root]+=x;
                mark[root]+=x;
                return;
            }
            pushdown(root);
            int mid=(l+r)>>1;
            if (ll<=mid) updata(lson,l,mid,ll,rr,x);
            if (rr>mid) updata(rson,mid+1,r,ll,rr,x);
            minn[root]=min(minn[lson],minn[rson]);
        }
    
        LL getans(int root,int l,int r,int ll,int rr){
            if (ll<=l&&r<=rr) return minn[root];
            pushdown(root);
            int mid=(l+r)>>1;
            if (rr<mid) return getans(lson,l,mid,ll,rr);
            else if (ll>=mid) return getans(rson,mid+1,r,ll,rr);
            else return min(getans(lson,l,mid,ll,rr),getans(rson,mid+1,r,ll,rr)); 
        }
    
    }Segment;
    
    
    int n;
    
    int pos[N];
    
    LL sum[N],a[N];
    
    int main(void) {
        read(n);
        for(int u,i=1;i<=n;++i){
            read(u);
            pos[u]=i;
        }
        for(int i=1;i<=n;++i){
            read(a[i]);
            sum[i]=a[i]+sum[i-1];
        }
        Segment.build(1,1,n-1,sum);
        LL ans=Segment.getans(1,1,n-1,1,n-1);
        for(int i=1;i<=n;++i){
            Segment.updata(1,1,n-1,1,pos[i]-1,a[pos[i]]);
            Segment.updata(1,1,n-1,pos[i],n-1,-a[pos[i]]);
            ans=min(ans,Segment.getans(1,1,n-1,1,n-1));
        }
        write(ans,'
    ');
        return 0;
    }
    


  • 相关阅读:
    LINUX中SHELL批量导入文件到DB2数据库
    LINUX使用SHELL对DB2数据库中的大表中的非月末数据进行分离
    LINUX之SHELL进行数据检查和调用存储过程
    LINUX中使用SHELL重跑DB2存储过程
    SHELL中自动备份DB2架构
    使用SHELL对DB2数据库表空间进行自动扩容
    LINUX系统中根据DB2名称杀掉进程
    LINUX下SHELL调用DB2公共函数之public_s.sh
    pycurl之调用公共方法--请求/上传/下载,解析json
    pyspark常用函数
  • 原文地址:https://www.cnblogs.com/Lanly/p/12242917.html
Copyright © 2011-2022 走看看