题意
一串数列,到第几个数为止,使得前面的数的总和大于等于全部总和的一半。很简单,只要注意精度问题,不要用前面的求和大于等于总和的一半,而应该是前面的求和的2倍大于等于总和来算。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<algorithm>
#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<n;i++){
scanf("%I64d",&a[i]);
all+=a[i];
}
ll x=0;
for(int i=0;i<n;i++){
x+=a[i];
if(2*x>=all){
cout<<i+1<<endl;
break;
}
}
}
B. Students in Railway Carriage
题意
给出一排座位和队伍a,队伍b的数量。座位本身有可坐与不可坐的。然后让我们分配a,b的座位。条件是a,b不能相邻坐着。问能坐的最大数量。
思路
我看到很多人都上了什么贪心啊,什么差值比较比较什么的,就我看来在数据范围可以接受的情况下,没有必要那样去做,对于各种特殊情况都要去考虑,反而加大难度。可以直接模拟。做2个判断值p1,p2来表示能不能坐a,b。唯一要思考的是对于a,b都能坐的位置应该坐谁?坐数量大的那个。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<algorithm>
#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<n;i++){
scanf("%c",&c);
ch[i]=c;
}
int p1=1,p2=1;
int ans=0;
for(int i=0;i<n;i++){
if(ch[i]=='.'){
if(p1==1&&p2==1){
if(a>=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<<ans<<endl;
}
题意
给一个数,去掉几个数字后他应当变成一个没有前导0的平方数。求一个最小的去掉的数字个数。如果不可能输出-1
思路
很明显,对于每个位置,我们可以取1或0,来表说这个位置留下了还是去掉了。然后检验是不是平方数,以及保留最小去掉的数目就可以了。注意的是对于每个位置取值我写了10个for循环(菜鸡是这样的)。但实际上我们可以这样认为,不是要考虑1或0吗?我们看成2进制,len作为数的位数。那么是不是i做一个0~2^len的循环?然后i转换成2进制来判断每一位上是0还是1,就可以了。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<algorithm>
#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<<num<<endl;
else cout<<-1<<endl;
}
题意
给了一串数字。从最小的开始,合并从前往后读到的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<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<algorithm>
#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<ll> vec[2*maxn];
map<ll,ll>m;
map<ll,ll>pm;
int main(){
int n;
cin>>n;
int nn=n;
ll num=1;
for(int i=0;i<n;i++){
scanf("%I64d",&a[i]);
if(m[a[i]]==0){
m[a[i]]=num;
pm[num]=a[i];
num++;
}
}
int len;
for(int i=0;i<2*maxn;i++) vec[i].clear();
for(int i=0;i<n;i++){
int k=m[a[i]];
b[i]=a[i];
vec[k].push_back(i);
int kk=vec[k].size();
while(kk>=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;i<n;i++){
if(b[i]!=0){
a[len++]=b[i];
}
}
printf("%d\n",len);
for(int i=0;i<len;i++){
if(i>0) printf(" ");
printf("%I64d",a[i]);
}
printf("\n");
}