比赛过程中很惨,比完把五题都写了。
第一题main roune有c个问题,选出n个人,additional round有d个问题,选出1个人。问选出m*n-k个人最少需要多少问题。
代码如下:
#include<iostream>
using namespace std;
int main(){
// freopen("data.txt","r",stdin);
ios::sync_with_stdio(false);
int c,d;
int n,m;
int k;
cin>>c>>d>>n>>m>>k;
int tot=m*n;
if(k>=tot){cout<<0<<endl;return 0;}
tot-=k;
if(d<c/n){
cout<<d*tot<<endl;
}
else{
int ans=0;
int tmp=tot/n;
ans+=c*tmp;
tot-=tmp*n;
if(d*tot<c)ans+=d*tot;
else ans+=c;
cout<<ans<<endl;
}
return 0;
}
第二题每个人提交题目的时候有一个编码,对于第k个人,如果有提交编号为x,那么前面一定有一个x-1,问是否成立
代码如下:
#include<iostream>
#include<cstring>
using namespace std;
int P[100050];
int main(){
// freopen("data.txt","r",stdin);
ios::sync_with_stdio(false);
int n;
cin>>n;
memset(P,-1,sizeof(P));
bool can=1;
while(n--){
int x,k;
cin>>x>>k;
if(x>P[k]+1){can=0;break;}
P[k]=x>P[k]?x:P[k];
}
if(can){cout<<"YES"<<endl;}
else cout<<"NO"<<endl;
return 0;
}
第三题,几个人踢足球,每个人都赢了相同的数量,问这几个人谁赢谁
代码如下:
#include<iostream>
#include<cstring>
using namespace std;
int graph[1005][1005];
int main(){
ios::sync_with_stdio(false);
int n,k;
cin>>n>>k;
int tot=n*(n-1)/2;
if(n*k>tot||k>=n){cout<<-1<<endl;return 0;}
memset(graph,0,sizeof(graph));
for(int i=1;i<=n;++i){
tot=0;
for(int t=1;t<=n;++t){
if(i==t)continue;
if(tot==k)break;
if(graph[i][t]==0&&graph[t][i]==0){
graph[i][t]=1;
graph[t][i]=-1;
tot++;
}
}
if(tot!=k){cout<<-1<<endl;return 0;}
}
cout<<n*k<<endl;
for(int t=1;t<=n;++t){
for(int i=1;i<=n;++i)
if(graph[i][t]==1)cout<<i<<' '<<t<<endl;
}
return 0;
}
第四题状压DP
参考了博客:http://blog.youkuaiyun.com/keshuai19940722/article/details/24104687
对每道题的状态进行压缩。将所有人按照需要的monitor进行排序,然后需要的monitor在DP过程中就可以不用考虑
前面写的时候忘记<<跟+的优先级了,错第二次了。。。
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct aa{
int sol;
ll cos;
ll monitor;
};
bool operator < (const aa &a,const aa &b){
return a.monitor<b.monitor;
}
aa f[100];
ll dp[(1<<20)+5];
int main(){
// freopen("data.txt","r",stdin);
ios::sync_with_stdio(false);
memset(dp,-1,sizeof(dp));
int n,m,b;
cin>>n>>m>>b;
for(int i=0;i<n;++i){
int num;
cin>>f[i].cos>>f[i].monitor>>num;
f[i].sol=0;
for(int t=0;t<num;++t){
int j;
cin>>j;
f[i].sol=f[i].sol|(1<<(j-1));
}
}
int fin=(1<<m)-1;
sort(f,f+n);
ll ans=((__int64)1<<60);
dp[0]=0;
for(int i=0;i<n;++i){
for(int t=0;t<fin;++t){
if(dp[t]==-1)continue;
int u=t|f[i].sol;
if(dp[u]==-1)
dp[u]=dp[t]+f[i].cos;
else {
dp[u]=min(dp[u],dp[t]+f[i].cos);
}
}
if(dp[fin]!=-1){
ans=min(ans,dp[fin]+f[i].monitor*b);
}
}
if(ans<(__int64)1<<60)
cout<<ans<<endl;
else cout<<-1<<endl;
return 0;
}
第五题要构造。如果一行的所有数的平方和还是一个数的平方,那么将这些数同时扩大n倍以后,仍然满足所有数的平方和是一个数的平方。
代码如下:
#include<iostream>
using namespace std;
void create(int n,int a[]){
if(n==1){a[1]=1;return;}
if(n==2){a[1]=3;a[2]=4;return ;}
if(n&1){
a[1]=2;
for(int i=2;i<n;++i){
a[i]=1;
}
a[n]=(n+1)/2;
}
else {
for(int i=1;i<n;++i){
a[i]=1;
}
a[n]=(n-2)/2;
}
}
int a[105];
int b[105];
int main(){
ios::sync_with_stdio(false);
int m,n;
cin>>n>>m;
create(n,a);
create(m,b);
for(int i=1;i<=n;++i){
for(int t=1;t<=m;++t){
cout<<a[i]*b[t]<<' ';
}
cout<<endl;
}
return 0;
}