Codeforces Round #762 (Div. 3)

题目列表

    • 1,A. Square String?-Codeforces Round #762 (Div. 3)
    • 2,B. Squares and Cubes-Codeforces Round #762 (Div. 3)
    • 3,C. Wrong Addition-Codeforces Round #762 (Div. 3)
    • 5,E. MEX and Increments-Codeforces Round #762 (Div. 3)

1,A. Square String?-Codeforces Round #762 (Div. 3)

题意:给一个字符串,判断它是否是一个子字符串输出了两遍。

题解:如果字符串的长度是奇数,输出no。m=x.size/2,i从0到m-1判断x[m+i]和x[i]是否相等即可,如果不相等输出no,直到最后输出yes。

AC代码:

#include 
#include 
 
using namespace std;
string x;
 
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>x;
        int i1,i2,i3,i4;
        if(x.size()%2==1){cout<<"NO"<<endl;continue;}
        int flag=0;
        for(i1=x.size()/2;i1<x.size();i1++)
        {
            if(x[i1-(x.size()/2)]!=x[i1]) {flag=1;break;}
        }
        if(flag==1) {cout<<"NO"<<endl;}
        else cout<<"YES"<<endl;
    }
    return 0;
}

2,B. Squares and Cubes-Codeforces Round #762 (Div. 3)

题意:p同学喜欢平方数和立方数。给出n,判断从1到n有多少个p喜欢的数字。注意,如果一个数既是平方数也是立方数,算是一个数。

题解:打表。先算出1-1e9之间既是平方数也是立方数的数。然后题目给定n之后,算n的2次根和3次根,两个数相加然后减掉重复的值。

解释:如果不打表的话必定超时。二分不知道可不可以,但是这种方法简单易懂。

总结,像这种既是平方也是立方,题目有时候不会告诉咱们,咱们需要自己去发现。

AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define ll long long
map<ll,int> it;
long long n,m;
ll b[50]={0,1,64,729,4096,15625,
46656,117649,262144,531441,1000000,
1771561,2985984,4826809,7529536,11390625,
16777216,24137569,34012224,47045881,64000000,
85766121,113379904,148035889,191102976,244140625,
308915776,387420489,481890304,594823321,729000000,
887503681};
int main()
{
//    freopen("1.txt","r",stdin);
    int t;
    ll i1,i2,i3,i4,i5;
//    for(i1=1;i1*i1<=1000000001;i1++)
//    {
//        it[i1*i1]++;
//    }
//    for(i1=1;i1*i1*i1<=1000000001;i1++)
//    {
//        if(it[i1*i1*i1]==1) cout<
//    }
    cin>>t;
    while(t--)
    {
        cin>>n;
        i1=(int)sqrt(n);
        i2=(int)(pow(n,1.0/3));
 
        i5=i2+1;
        if(i2*i2*i2<n&&i5*i5*i5>n) ;
        else if(i5*i5*i5==n) i2=i5;
//        cout<
        for(i3=1;i3<=31;i3++)
        {
            if(b[i3]>n) break;
            else i1--;
        }
        cout<<i1+int(i2)<<endl;
 
    }
    return 0;
}

3,C. Wrong Addition-Codeforces Round #762 (Div. 3)

题意:T同学的加法没有进位,也就是如果两个当两个数相加小于10的时候结果是正确的,如果两个数相加大于10,T直接把和数写到底下,但依次相加,从有向左是正确的。给出被加数a和和值s,问加数是多少,或者不存在输出/1。

题解:判断两个s和a哪个大,如果a大直接输出-1。之后从两个数的最低位开始比较,如果a的当前一位大于s的当前一位,那s就取两位数减去a的当前一位。否则,a的一位减去s的一位。

AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
string x,y,z;
int main()
{
//    freopen("1.txt","r",stdin);
    int t;
    int i1,i2,i3,i4,i5,i6;
    int p,q;
    cin>>t;
    while(t--)
    {
        cin>>x>>y;
        z="o";
        if(y.size()<x.size()) {cout<<-1<<endl;continue;}
        if(x.size()==y.size())
        {
            int flag=0;
            for(i1=0;i1<x.size();i1++)
            {
                if(x[i1]==y[i1]) continue;
                else if(x[i1]<y[i1]) break;
                else flag=1;
            }
            if(flag==1) {cout<<-1<<endl;continue;}
        }
        p=x.size()-1;
        q=y.size()-1;
        int flag=0;
        while(1)
        {
            if(p==q&&q==-1) break;
            if(p==-1) {
                for(;q>=0;q--)
                    z+=y[q];
                break;
            }
            if(x[p]<=y[q]) {z+=(y[q]-x[p]+'0');/*cout<<(char)(y[q]-x[p]+'0')<p--;q--;continue;}
            if(q==0||y[q-1]!='1') {flag=1;break;}
            z+=(10+y[q]-x[p]+'0');
            p--;q--;q--;
        }
//        cout<
        if(flag==1) {cout<<-1<<endl;}
        else {string ans="";
 
            for(i1=z.size()-1;i1>0;i1--)
                if(flag) ans+=z[i1];
                else if(z[i1]!='0') {flag=1;ans+=z[i1];}
            for(i1=0;i1<ans.size();i1++)
            {
                cout<<ans[i1];
            }
            cout<<endl;
        }
    }
    return 0;
}

5,E. MEX and Increments-Codeforces Round #762 (Div. 3)

题意:给出n个元素数组。你要输出n+1个数。第i个数是进行x次操作后的数组的mex值为i-1,x为操作的最小值。数组的mex是指从0开始数组没有出现的最小整数。每次操作可以选择任意一个整数,并且加一。注意,这n+1个数,每次的实验都是独立的,也就是每次开始的数组都是最初的数组。

题解:第i个数是dp[i]=dp[i-1]-it[i-1]+it[i]。第0个数是dp[0]=it[0]。还有一种棘手的情况看代码,太麻烦了,说不清楚。

解释:如果前i-1个数在数组中都有,分两种情况,如果第i个数没有,那直接是前i-1个数的操作数,第i个数有,就是把第i个数的出现次数加一,也就是把所有的第i个数都变为i+1。那问题是前i-1个数为什么都有,分有和没有两种情况。不存在的情况就是q

总结,这题确实有难度,其实暴力很容易写出了,但是超时。所以用dp,但是要分析特殊情况。

AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
#define ll long long
ll a[200010],dp[200010],dp1[200010],b[200010];
ll n,m,p;
map<ll,ll> it;
 
int main()
{
 //   freopen("1.txt","r",stdin);
    int t;
    ll i1,i2,i3,i4,i5;
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(b,0,sizeof(b));
        it.clear();
        for(i1=1;i1<=n;i1++)
        {
            scanf("%d",&a[i1]);
            it[a[i1]]++;
        }
        ll p=0;
        m=0;
        ll m1=0;
        while(m<=n)
        {
            if(p<m) {break;}
            ll sum=0,p1=p;
            if(m==0) {cout<<it[0];p+=it[m];dp[0]=it[m];m++;continue;}
//            cout<
            dp[m]=dp[m-1]-it[m-1]+it[m];
            if(it[m-1]==0) {dp[m]+=m-b[m1]-1;it[b[m1]]--;if(it[b[m1]]==1) m1--;it[m-1]++;}
            if(it[m]>1) b[++m1]=m;
            cout<<" "<<dp[m];
            p+=it[m];
            m++;
        }
 
        if(m!=n+1)
        {
            for(;m<=n;m++)
                cout<<" "<<-1;
        }
        cout<<endl;
    }
    return 0;
}

你可能感兴趣的:(笔记,算法,c++)