zoukankan      html  css  js  c++  java
  • 《Codeforces Round #667 (Div. 3)》

    A:签到题

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<string,int> pii;
    const int N = 1e5+5;
    const int M = 2e5+5;
    const LL Mod = 199999;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
     
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            int a,b;a = read(),b = read();
            if(a > b) swap(a,b);
            int dis = b-a;
            int ma = dis/10;
            if(ma*10 == dis) printf("%d
    ",ma);
            else printf("%d
    ",ma+1);
        }
        //system("pause");
    }
    View Code

    B:这里假设了一下减去个值为t0,然后求出的乘积为一个开口向下的二次函数。

    那么要最小化乘积,显然是在两边,也就是极限的两个位置,那么就是先让x尽可能小,然后让y尽可能小,求一下两者之间的最小即可

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<string,int> pii;
    const int N = 1e5+5;
    const int M = 2e5+5;
    const LL Mod = 199999;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
    
    LL slove(LL a,LL b,LL x,LL y,LL n)
    {
        LL dis1 = min(n,a-x);
        a -= dis1;
        n -= dis1;
        LL dis2 = min(n,b-y);
        b -= dis2;
        return a*b;
    }
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            LL a,b,x,y,n;
            a = read(),b = read(),x = read(),y = read(),n = read();
            LL ans = slove(a,b,x,y,n);
            ans = min(ans,slove(b,a,y,x,n));
            printf("%lld
    ",ans);
        }
       // system("pause");
    }
    View Code

    C:可以发现,在给定的两个值中间能插入越多的数,差距就会越大,然后剩余要插的就会越少。

    那么我们就去找可以在中间插入多少,然后就找到了差距,然后先向小的方向插剩余的,然后再插大的方向

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<string,int> pii;
    const int N = 1e5+5;
    const int M = 2e5+5;
    const LL Mod = 199999;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
    
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            int n,x,y;n = read(),x = read(),y = read();
            n -= 2;
            vector<int> ans;
            ans.push_back(x);
            if(n == 0) ans.push_back(y);
            else
            {
                int dis = y-x,ma = 0;
                int m = sqrt(dis);
                for(rg int i = 1;i <= dis-1;++i)
                {
                    if(dis%i == 0 && dis/i-1 <= n)
                    {
                        ma = i;
                        break;
                    }
                }
                if(ma == 0)
                {
                    ans.push_back(y);
                    int dis = y-x;
                    for(rg int i = x-dis;i > 0 && n > 0;i -= dis) ans.insert(ans.begin(),i),n--;
                    for(rg int i = y+dis;n > 0;i += dis) ans.push_back(i),n--;
                }
                else
                {
                    int dis = ma;
                    for(rg int i = x+dis;i < y;i += dis) ans.push_back(i),n--;
                    for(rg int i = x-dis;i > 0 && n > 0;i -= dis) ans.insert(ans.begin(),i),n--;
                    for(rg int i = y+dis;n > 0;i += dis) ans.push_back(i),n--;
                    ans.push_back(y);
                }
            }
            for(rg int i = 0;i < ans.size();++i) printf("%d%c",ans[i],i == ans.size()-1 ? '
    ' : ' ');
        }
        //system("pause");
    }
    View Code

    D:注意题目,满足小于等于即可。

    模拟进制转化,从最小位开始向上进位,每次进位后都满足减去部分值。

    当<=时就退出,注意中途记录答案值,不然最后的话,要把值进完再找最后的值相减,很麻烦。

    证明一下为什么这样肯定是最小。

    因为我们是不断从小开始进位,数值是在不断增大,但是现在最低位都为0了,如果去增加最低位,显然不会对答案产生贡献,那么,就满足增加最高位之后,第一次满足的肯定是最小。(有点口胡~)

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<string,int> pii;
    const int N = 1e5+5;
    const int M = 2e5+5;
    const LL Mod = 199999;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
    
    int a[25],len;
    int Get_dig()
    {
        int sum = 0;
        for(rg int i = 1;i <= len;++i) sum += a[i];
        return sum;
    }
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            memset(a,0,sizeof(a));
            string s;cin >> s;
            int ss;ss = read();
            len = s.size();
            for(rg int i = 0;i < len;++i) a[len-i] = s[i]-'0';
            int dig = Get_dig();
            if(dig <= ss) printf("0
    ");
            else
            {
                LL ans = 0,ma = 1;
                for(rg int i = 1;i <= len;++i,ma *= 10)
                {
                    ans += (10-a[i])*ma;
                    a[i] = 0;
                    a[i+1]++;
                    if(Get_dig() <= ss) break;
                }
                printf("%lld
    ",ans);
            }
        }
      //  system("pause");
    }
    View Code

    E:这题我感觉不是很难,一发就过了。

    题意很显然,我们先排序去重。map记录下每个位置重复的个数。

    然后我们可以去枚举第一个放的线段,显然我们枚举的是左边界,并且显然这个左边界在存在的点上更优。

    第一条显然的覆盖点数我们可以二分+前缀和求出。

    然后我们再去枚举第二个放的线段,显然这个线段的左起点应该在当前区间右边界外更优。

    那么此时,我们枚举两个的复杂度为n^2。这显然会T。

    但是,我们可以先处理出dp[i]表示i~n里选择某个点为起点的最优覆盖长度的最大值。

    然后枚举第一个线段时,对于第二个线段就可以高效求出了。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<string,int> pii;
    const int N = 2e5+5;
    const int M = 2e5+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
    
    int x[N],y[N];
    LL sum[N],dp[N];//dp[i]-i~n的最优价值
    int main()
    {
        int ca;ca = read();
        while(ca--)
        {
            int n,k;n = read(),k = read();
            unordered_map<int,int> mp;
            for(rg int i = 1;i <= n;++i) x[i] = read(),mp[x[i]]++;
            for(rg int i = 1;i <= n;++i) y[i] = read();
            sort(x+1,x+n+1);
            int len = unique(x+1,x+n+1)-x-1;
            sum[0] = 0;
            for(rg int i = 1;i <= len;++i) sum[i] = sum[i-1]+mp[x[i]];
            int mx = x[len];
            dp[len+1] = 0;
            for(rg int i = len;i >= 1;--i)
            {
                LL pos = x[i]+k,ma;
                if(pos >= mx) ma = sum[len]-sum[i-1];
                else 
                {
                    int pt = upper_bound(x+1,x+len+1,pos)-x;
                    ma = sum[pt-1]-sum[i-1];
                } 
                dp[i] = max(dp[i+1],ma);
            }
            LL ans = 0;
            for(rg int i = 1;i <= len;++i)
            {
                int pos = x[i]+k;
                LL tmp1,tmp2;
                if(pos >= mx) 
                {
                    tmp1 = sum[len]-sum[i-1];
                    tmp2 = 0;
                }
                else
                {
                    int pt = upper_bound(x+1,x+len+1,pos)-x;
                    tmp1 = sum[pt-1]-sum[i-1];
                    tmp2 = dp[pt];
                }
                ans = max(ans,tmp1+tmp2);
            }
            printf("%lld
    ",ans);
        }    
       // system("pause");    
    }
    View Code

    F:第一眼就感觉是dp,无从下手。太菜了太菜了~~

    注意t只有两个字符。

    定义dp[i][j][k]表示前i个位置,变换了j个数,k个t0的最多方案数。

    注意的是要判断两个字符相同时的影响。转移的话就三种,si不变,si变t0,si变t1。注意这里的方案都算的是到i位置的方案数。

    对于i~n的方案数都还未计算,然后可以发现,到了n位置,n+1位置可能才会记录到n位置的方案数,所以最后也要计算到n+1位置。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<string,int> pii;
    const int N = 2e5+5;
    const int M = 2e5+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
    
    LL dp[205][205][205];//dp[i][j][k]-前i个位置更改了j个字符,t0的数量为k时的方案数
    int main()
    {
        int n,k;n = read(),k = read();
        string s;cin >> s;
        string t;cin >> t;
        char t0 = t[0],t1 = t[1];
        memset(dp,-0x3f,sizeof(dp));
        LL low = dp[0][0][0];
        LL ans = 0;
        dp[1][0][0] = 0;
        for(rg int i = 1;i <= n;++i)
        {
            char ch = s[i-1];
            for(rg int j = 0;j <= k;++j)
            {
                for(rg int z = 0;z <= n;++z)
                {
                    if(dp[i][j][z] == low) continue;
                   // printf("i is %d j is %d z is %d
    ",i,j,z);
                    int num1 = (ch == t0);
                    int num2 = (ch == t1);
                    dp[i+1][j][z+num1] = max(dp[i+1][j][z+num1],dp[i][j][z]+num2*z);//不变si
                    if(j < k)//一定要<,当=时无法再变换
                    {
                        int same = (t0 == t1);
                        dp[i+1][j+1][z+1] = max(dp[i+1][j+1][z+1],dp[i][j][z]+same*z);//变成t1
                        dp[i+1][j+1][z+same] = max(dp[i+1][j+1][z+same],dp[i][j][z]+z);//变成t1
                    }
                }
            }
        }
        for(rg int i = 1;i <= n+1;++i)
            for(rg int j = 0;j <= n;++j)
                for(rg int k = 0;k <= n;++k) ans = max(ans,dp[i][j][k]);
        printf("%lld
    ",ans);
        //system("pause");    
    }
    View Code
  • 相关阅读:
    10.11-10.16
    10.8-10.10
    9.26-28
    9.29css继承属性
    表单的学习
    排版
    css补充
    今天学的新内容
    新内容
    文本样式的修改
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13633098.html
Copyright © 2011-2022 走看看