Educational Codeforces Round 42 (Rated for Div. 2) A~D

A.Equator 

题意

一串数列,到第几个数为止,使得前面的数的总和大于等于全部总和的一半。很简单,只要注意精度问题,不要用前面的求和大于等于总和的一半,而应该是前面的求和的2倍大于等于总和来算。

代码

#include
#include
#include
#include
#include
#include
#include
#define mem(a,b) memset(a,b,sizeof a)
#define mal(a,b) a=(b*)malloc(sizeof(b))
#define st std::ios::sync_with_stdio(false);
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
const double e=1e-8;
ll a[2*maxn];
int main(){
    int n;
    cin>>n;
    ll all=0;
    for(int i=0;i=all){
            cout<

B. Students in Railway Carriage

题意

给出一排座位和队伍a,队伍b的数量。座位本身有可坐与不可坐的。然后让我们分配a,b的座位。条件是a,b不能相邻坐着。问能坐的最大数量。

思路

我看到很多人都上了什么贪心啊,什么差值比较比较什么的,就我看来在数据范围可以接受的情况下,没有必要那样去做,对于各种特殊情况都要去考虑,反而加大难度。可以直接模拟。做2个判断值p1,p2来表示能不能坐a,b。唯一要思考的是对于a,b都能坐的位置应该坐谁?坐数量大的那个。

代码

#include
#include
#include
#include
#include
#include
#include
#define mem(a,b) memset(a,b,sizeof a)
#define mal(a,b) a=(b*)malloc(sizeof(b))
#define st std::ios::sync_with_stdio(false);
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
const double e=1e-8;
char ch[2*maxn];
int main(){
    int n;
    int a,b;
    scanf("%d %d %d",&n,&a,&b);
    char c;
    getchar();
    for(int i=0;i=b&&a>0){
                    a--;
                    ans++;
                    p1=0;
                }else if(b>a&&b>0){
                    b--;
                    ans++;
                    p2=0;
                }
            }else if(p1==1&&a>0){
                a--;
                ans++;
                p1=0;
                p2=1;
            }else if(p2==1&&b>0){
                b--;
                ans++;
                p1=1;
                p2=0;
            }else{
                p1=1;
                p2=1;
            }
        }else{
            p1=1;
            p2=1;
        }
    }
    cout<

C. Make a Square

题意

给一个数,去掉几个数字后他应当变成一个没有前导0的平方数。求一个最小的去掉的数字个数。如果不可能输出-1

思路

很明显,对于每个位置,我们可以取1或0,来表说这个位置留下了还是去掉了。然后检验是不是平方数,以及保留最小去掉的数目就可以了。注意的是对于每个位置取值我写了10个for循环(菜鸡是这样的)。但实际上我们可以这样认为,不是要考虑1或0吗?我们看成2进制,len作为数的位数。那么是不是i做一个0~2^len的循环?然后i转换成2进制来判断每一位上是0还是1,就可以了。

代码

#include
#include
#include
#include
#include
#include
#include
#define mem(a,b) memset(a,b,sizeof a)
#define mal(a,b) a=(b*)malloc(sizeof(b))
#define st std::ios::sync_with_stdio(false);
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
const double e=1e-8;
ll ans[maxn];
int a[10];
int main(){
    for(ll i=1;i<=maxn;i++){
        ans[i]=i*i;
    }
    ll n;
    scanf("%I64d",&n);
    int len=0;
    ll nn=n;
    while(nn>0){
        a[len]=nn%10;
        nn/=10;
        len++;
    }
    int num=maxn;
    int b[10];
    for(b[0]=0;b[0]<=1;b[0]++){
        for(b[1]=0;b[1]<=1;b[1]++){
            for(b[2]=0;b[2]<=1;b[2]++){
                for(b[3]=0;b[3]<=1;b[3]++){
                    for(b[4]=0;b[4]<=1;b[4]++){
                        for(b[5]=0;b[5]<=1;b[5]++){
                            for(b[6]=0;b[6]<=1;b[6]++){
                                for(b[7]=0;b[7]<=1;b[7]++){
                                    for(b[8]=0;b[8]<=1;b[8]++){
                                        for(b[9]=0;b[9]<=1;b[9]++){
                                            ll bb=0;
                                            int y=0;
                                            int flag=1;
                                            for(int k=len-1;k>=0;k--){
                                                if(bb==0&&b[k]!=0&&a[k]==0){
                                                    flag=0;
                                                    break;
                                                }
                                                if(b[k]!=0){
                                                    y++;
                                                    bb*=10;
                                                    bb+=a[k];
                                                }
                                            }
                                            if(!flag) continue;
                                            ll z=sqrt(bb);
                                            if(z*z==bb&&z>=1){
                                                num=min(num,len-y);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    if(num!=maxn)cout<

D. Merge Equals

题意

给了一串数字。从最小的开始,合并从前往后读到的2个相同的数字,后一个数字变成2倍,前一个数字删去。问最后合并完是什么样子的。

思路

其实很简单的,或者说,根本不用管是不是从最小的开始。然后又用优先队列的。的确优先队列比较快是简单。但是我当时没有想到。。。。直接vector和map操作。输入数组ary[n]。首先因为数字很大,vector数组开不过来我用了map映射。然后对于操作。我从i=0开始读数,然后把i压入到vec[ary[i]]。然后每次压入判断该容器的大小是不是等于2了,如果是的那么读取容器里面的第一个和第二个数字,即是他们所在 的位置,把前面位置上的数字变成0后面的变成原来的2倍。清空容器,然后把第二个数字压入到vec[ary[i]*2]的位置中去,判断这个容器是不是==2,直到把整个数组处理完成,读入下一个ary[i+1]。注意若是用map这边很多都是不能这样写的,要做转换,不是单纯的ary[i]*2,但是为了方便理解故如此。

代码

#include
#include
#include
#include
#include
#include
#include
#define mem(a,b) memset(a,b,sizeof a)
#define mal(a,b) a=(b*)malloc(sizeof(b))
#define st std::ios::sync_with_stdio(false);
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
const double e=1e-8;
ll a[2*maxn];
ll b[2*maxn];
vector vec[2*maxn];
mapm;
mappm;
int main(){
    int n;
    cin>>n;
    int nn=n;
    ll num=1;
    for(int i=0;i=2){
            ll weizhi=vec[k][0];
            ll wz=vec[k][1];
            b[vec[k][1]]=pm[k]*2;
            b[weizhi]=0;
            vec[k].clear();
            if(m[pm[k]*2]==0){
                m[pm[k]*2]=num;
                pm[num]=pm[k]*2;
                num++;
            }
            k=m[pm[k]*2];
            vec[k].push_back(wz);
            kk=vec[k].size();
        }
    }
    len=0;
    for(int i=0;i0) printf(" ");
        printf("%I64d",a[i]);
    }
    printf("\n");
}

你可能感兴趣的:(个人的解题)