题目链接:http://codeforces.com/contest/1003
A题题意:给定N个值,每个集合只能放不相同的数,问把所有值放进去最少需要多少个集合。
A题题解:直接暴力统计最多出现的数的次数即可。
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 1e5+7;
int a[105];
int n;
int main(int argc, char const *argv[])
{
cin>>n;
int ans = 0;
_for(i,1,n)
{
int x;
cin>>x;
a[x]++;
ans=max(ans,a[x]);
}
cout<<ans<<endl;
return 0;
}
B题题意:给定a,b,x三个数,构造一个长度为a+b的数列,其中0的个数等于a,1的个数等于b,a[i]!=a[i+1]的个数等于x。
B题题解:对x分奇偶分情况讨论,然后在两边将多余的01输出即可。
AC代码:
/*
* @Author: 王文宇
* @Date: 2018-07-03 22:40:50
* @Last Modified by: 王文宇
* @Last Modified time: 2018-07-03 23:04:11
*/
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 1007;
char s[maxn];
int a,b,x;
int main(int argc, char const *argv[])
{
cin>>a>>b>>x;
int now = 1;
int l = x;
if(x&1)
{
if(a>b)
{
while(x>1)
{
a--;
b--;
x-=2;
}
while(a--)cout<<0;
while(l>1)
{
cout<<"10";
l-=2;
}
while(b--)cout<<1;
cout<<endl;
}
else
{
while(x>1)
{
a--;
b--;
x-=2;
}
while(b--)cout<<1;
while(l>1)
{
cout<<"01";
l-=2;
}
while(a--)cout<<0;
cout<<endl;
}
}
else
{
if(a>b)
{
a-=x/2;
b-=x/2;
while(a>1)
{
cout<<"0";
a--;
}
while(x>0)
{
cout<<"01";
x-=2;
}
while(b--)cout<<"1";
cout<<0<<endl;
}
else
{
b-=x/2;
a-=x/2;
while(b>1)
{
cout<<"1";
b--;
}
while(x>0)
{
cout<<"10";
x-=2;
}
while(a--)cout<<"0";
cout<<1<<endl;
}
}
return 0;
}
C题题意:给定N个数值和K,求一个长度不小于K的子序列,使其平均值最大。
C题题解:因为n<=5000,所以n^2暴力即可。
AC代码:
/*
* @Author: 王文宇
* @Date: 2018-07-03 23:11:04
* @Last Modified by: 王文宇
* @Last Modified time: 2018-07-03 23:19:36
*/
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 5005;
int n,k;
double ans;
int a[maxn];
int sum[maxn];
int main(int argc, char const *argv[])
{
cin>>n>>k;
_for(i,1,n)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
_for(i,0,n-k)
{
_for(j,i+k,n)
{
int h = sum[j]-sum[i];
double now = (double)h/(double)(j-i);
ans = max(now,ans);
}
}
printf("%.15lf\n",ans);
return 0;
}
D题题意:给定一个只包含2的倍数的数组,然后给定Q个询问,对于每次询问的整数找到取最少的数组中的数的和等于被询问数,无法构成输出-1
D题题解:将给定的数拆成2进制统计每个进制然后对于每个询问暴力即可。
AC代码:
/*
* @Author: 王文宇
* @Date: 2018-07-03 23:47:28
* @Last Modified by: 王文宇
* @Last Modified time: 2018-07-04 00:49:17
*/
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 2e5+7;
int n,q;
int a[maxn],num[maxn];
int main(int argc, char const *argv[])
{
cin>>n>>q;
_for(i,1,n)
{
cin>>a[i];
int k = -1;
while(a[i])
{
k++;
a[i]/=2;
}
num[k]++;
}
_for(i,1,q)
{
int x;
cin>>x;
int ss = 0;
int now = 0;
int ok = 0;
long long k = 1;
long long next = (long long)x;
while(k<=next)
{
k*=2;
now++;
}
while(next>0)
{
k/=2;
//cout<<now<<endl;
now--;
if(k>next)continue;
if(num[now]*k>=next)
{
int h = next/k;
next-=k*h;
ss+=h;
}
else
{
ss+=num[now];
next-=num[now]*k;
}
if(now==-1)
{
ok = 1;
break;
}
}
if(ok||next<0)cout<<"-1"<<endl;
else cout<<ss<<endl;
}
return 0;
}
E题题意:给定n,d,k,构造一棵无向树,结点个数为n,直径为d,每个结点的深度不大于k。
E题题解:首先特判不存在的情况,然后先构造出直径,然后在直径上尽可能的加边即可。最后判断加的边是不是等于n-1即可。
AC代码:
/*
* @Author: 王文宇
* @Date: 2018-07-03 23:34:42
* @Last Modified by: 王文宇
* @Last Modified time: 2018-07-04 04:02:26
*/
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=a;i<=b;i++)
const int maxn = 4e5+7;
int n,d,k,now;
vector<pair<int,int> > Q;
vector<int> E[maxn];
void dfs(int x,int y,int z)
{
if(z==y)return;
for(int i=0;i<k-1-(y==0)&&now<n;i++)
{
now++;
int u = now;
Q.push_back(make_pair(x,u));
dfs(u,y+1,z);
}
}
int main(int argc, char const *argv[])
{
cin>>n>>d>>k;
if(n<(d+1))
{
cout<<"NO"<<endl;
return 0;
}
if(k==1)
{
if(d==1&&n==2)cout<<"YES\n1 2"<<endl;
else cout<<"NO"<<endl;
return 0;
}
now = d+1;
_for(i,1,d)
{
E[i].push_back(i+1);
Q.push_back(make_pair(i,i+1));
}
_for(i,1,d+1)
{
dfs(i,0,min(i-1,d+1-i));
}
if(now<n)
{
cout<<"NO"<<endl;
return 0;
}
cout<<"YES"<<endl;
_for(i,0,n-2)cout<<Q[i].first<<" "<<Q[i].second<<endl;
return 0;
}