训练报告 (2014-2015) 2014, Samara SAU ACM ICPC Quarterfinal Qualification Contest

Solved A Gym 100488A Yet Another Goat in the Garden
  B Gym 100488B Impossible to Guess
Solved C Gym 100488C Lost Temple
Solved D Gym 100488D Toy Soldiers
Solved E Gym 100488E Just Change a Word
Solved F Gym 100488F Two Envelopes
Solved G Gym 100488G Change-making Problem
  H Gym 100488H Tony Hawk's Pro Skater
Solved I Gym 100488I Map Coloring
  J Gym 100488J Hyperdromes Strike Back
Solved K Gym 100488K Two Pirates
  L Gym 100488L Two Heads Are Better
Solved M Gym 100488M Construct a Permutation

链接:2014, Samara SAU ACM ICPC Quarterfinal Qualification Contest

打了不到2个小时,3星

AC 4/13 
真滴菜
A了4个题,然后挂机,然后溜了...
G 题没过滤掉无效情况 
D 没考虑一开始就不用涂的情况 

实际上
如果把M题,C题的时间拿来试A的题意,估计秒了
然后把I题的思路勇敢的推倒,搞个暴力,稳到5-6题也是可能的…

题解:

A 计算几何 

出题人没说清楚题意,简直智障,求的确实是百分比,和我猜的一样...

很显然,把三个角的未覆盖放在一起,可以得到一个黑洞的外接三角形...

小三角形和大三角形的面积之比就是(黑洞的半径/大三角形内接圆半径)^2

大三角形的面积可以用海伦公式得到

然后小三角形的面积减去黑洞的面积就是没有覆盖的面积...

写的时候我一度以为是直角三角形..

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int a1[maxn],a2[maxn];
int main(){
//#define test
#ifdef test
	freopen("in.txt","r",stdin);freopen("out1.txt","w",stdout);
#endif

	double a,b,c,r;
	double PI=2.0*acos(0);
	double num[3];
	while(cin>>num[0]>>num[1]>>num[2]>>r){
		sort(num,num+3);
		a=num[0],b=num[1],c=num[2];
		double l=(a+b+c)/2.0;
		double sum=sqrt(l*(l-a)*(l-b)*(l-c));
		double R=2.0*sum/(a+b+c);
		double ss=sum*(r/R)*(r/R)-r*r*PI;
		double ans=(1.0-ss/sum);
		printf("%.16f\n",ans);
	}

#ifdef test
	fclose(stdin);fclose(stdout);system("out1.txt");
#endif
	return 0;
}

C

a*b=k(a+b)

给k 求所有的a和b

推一下公式 发现可以转化为a=k+(k^2)/(b-k)

所以只要得到k^2的所有因子,然后把这些因子+k就是b,k^2/这些因子再+k就是a...

显然 k^2的因字即k的因子,而k^2=k*k(废话),因此任意两个k的因子相乘,也一定是k^2的因子..

然后暴力就行了...

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
ll casn,n,m,k;
set<ll> vis;
ll num[maxn];
int cnt=0;
int main(){
//#define test
#ifdef test
	freopen("in.txt","r",stdin);freopen("out1.txt","w",stdout);
#endif
	while(cin>>k){
		cnt=0;
		for(int i=1;i*i<=k;i++){
			if(k%i) continue;
			num[cnt++]=i;
			if(i*i!=k) num[cnt++]=k/i;
		}
		vis.clear();
		for(int i=0;i<cnt;i++){
			for(int j=0;j<cnt;j++){
				vis.insert(num[i]*num[j]);
			}
		}
		cout<<vis.size()<<endl;
		for(auto i=vis.begin();i!=vis.end();i++){
			cout<<(*i+k)<<' '<<k+(k*k)/(*i)<<endl;
		}
	}
#ifdef test
	fclose(stdin);fclose(stdout);system("out1.txt");
#endif
	return 0;
}

D

水题

用map保存种颜色的数量,如果修改的过程中数量为零,则删除

当size==1的时候 结束

注意一开始就size==1的情况....

#include <string.h>
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <map>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int a,b,c;
int num[maxn];
map<int,int> vis;

int main(){
// #define test
#ifdef test
	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif

	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&num[i]);
		vis[num[i]]++;
 }

	cin>>m;
	int ans=0;
	if(vis.size()==1) {
			ans=-1;
	}
	for(int i=1;i<=m;i++){
		scanf("%d %d",&a,&b);
		if(ans) continue;
		if(vis.size()==1) {
			ans=i;
		}
		vis[num[a]]--;
		if(vis[num[a]]==0) vis.erase(num[a]);
		vis[b]++;
		num[a]=b;
		if(vis.size()==1) {
			ans=i;
		}
	}
	if(!ans)cout<<-1<<endl;
	else cout<<max(ans,0)<<endl;


#ifdef test
	fclose(stdin);fclose(stdout);system("out.txt");
#endif
	return 0;
}

E

水题

给一个字符串

每次找两个相邻的不同字母删除,问是否能删光

我想递推,但zc直接想出了只要统计是否有一种字符数量大于一半,大于则不可能

逻辑也比较显然,只要种类不是1种 就肯定能继续删下去,每次删除这两种字符都会--,但是如果一开始就大于一半,显然不可能,其他的情况必然有解

注意奇数情况

#include <string.h>
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <map>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
char s[maxm];
int vis[1000];
int main(){
//#define test
#ifdef test
	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
	scanf("%s",s);
	n=strlen(s);
	int flag=1;
	if(n&1) flag=0;
	for(int i=0;i<n;i++){
		vis[s[i]]++;
	}
	int cnt=0;
	for(int i=0;i<1000;i++){
		cnt=max(vis[i],cnt);
	}
	if(cnt<=n/2&&flag) cout<<"YES"<<endl;
	else cout<<"NO"<<endl;

#ifdef test
	fclose(stdin);fclose(stdout);system("out.txt");
#endif
	return 0;
}

F

水题...

#include <string.h>
#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int a,b,c;

int main(){
//#define test
#ifdef test
	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif

	cin>>a>>b>>c;
	if(c>b) puts("Stay with this envelope");
	else puts("Take another envelope");

#ifdef test
	fclose(stdin);fclose(stdout);system("out.txt");
#endif
	return 0;
}

G

水题

直接贪心就好..

#include <string.h>
#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;

int casn,n,m,k;
#define IO ios::sync_with_stdio(false)
long long a[maxn];
long long chu[maxn];
int main(){

IO;

long long ans=0;
while(cin>>n>>m)
{
	for(int i=1;i<=n;i++)
	cin>>chu[i];
	n++;
	memset(a,0,sizeof(a));
	a[1]=1;
	int cnt=0;
	for(int i=2;i<=n;i++)
	{
		a[i]=a[i-1]*chu[i-1];
		cnt=i;
		if(a[i]>1e11) {

			break;
		}
  }
  //cout<<a[2]<<endl;
   ans=0;
   int temp=0;
   n=cnt;
	 for(int i=n;i>=1;i--)
	 {
	 	if(a[i]==0) continue;
			 temp=m/a[i];
			 ans+=temp;
			 if(temp>0)
			 {
					m-=a[i]*temp;
			 }
	 }
	 cout<<ans<<endl;
}


	return 0;
}

给一个无向连通图,让你去染色,两点的颜色不同当且仅当两点相邻

比赛的时候题读错了,必须仔细读才行,幸亏给了sample3...不然得WA一天

不过一开始说dfs,也确实是可以dfs的...不过是在原图边集的补集上进行dfs,暴力上一种染色就行

以下是非dfs的n^2算法

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e3+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int g[maxn][maxn];
int clr[maxn];
int vis[maxn];
int main(){
//#define test
#ifdef test
	freopen("in.txt","r",stdin);freopen("out1.txt","w",stdout);
#endif
	while(cin>>n>>m>>k){
		memset(g,0,sizeof g);
		for(int i=0;i<m;i++){
			int a,b;
			scanf("%d%d",&a,&b);
			g[a][b]=g[b][a]=1;
		}
		memset(clr,0,sizeof clr);
		for(int i=1;i<=n;i++){
			if(clr[i]) continue;
			memset(vis,0,sizeof vis);
			for(int j=1;j<=n;j++){
				if(i!=j&&g[i][j]) vis[clr[j]]=1;
			}
			int tmp=1;
			while(vis[tmp])tmp++;
			clr[i]=tmp;
		}
		int flag=1;
		for(int i=1;i<=n&&flag;i++){
			if(clr[i]>k||!clr[i]) flag=0;
			for(int j=i+1;j<=n&&flag;j++){
				if(g[i][j]&&clr[i]==clr[j])flag=0;
				if(!g[i][j]&&clr[i]!=clr[j]) flag=0;
			}
		}
		if(flag){
			for(int i=1;i<=n;i++) cout<<clr[i]<<' ';
			cout<<endl;
		}else puts("-1");
	}
#ifdef test
	fclose(stdin);fclose(stdout);system("out1.txt");
#endif
	return 0;
}

K

两个人,n个物品顺序拜访,价值不同,轮流拿东西,只不过A先手,且每次可以任意拿,B后手且每次只能顺序拿剩下的

每次直接假设A拿走2个,然后每拿2个就把A拿过的最小的那个留给B,维护两人的和就行

简单来说,A可以选择让B拿走当前这个还是下一个,但A也可以拿后面的,让B既拿这个,也拿下一个

就用多重集合保存A可以拿的,每次把可以拿的最小的分给B即可

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
multiset<int> vis;

int main(){
//#define test
#ifdef test
	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif

	while(cin>>n){
		vis.clear();
		long long ans1=0,ans2=0;
		for(int i=1;i<=n;i++){
			int t;
			cin>>t;
			ans1+=t;
			vis.insert(t);
			if(i%2==0){
				ans1-=*vis.begin();
				ans2+=*vis.begin();
				vis.erase(vis.begin());
			}
		}
		cout<<ans1<<' '<<ans2<<endl;
	}

#ifdef test
	fclose(stdin);fclose(stdout);system("out.txt");
#endif
	return 0;
}

M

给你A,B

要求一个长度为N的数列,为1-N的一个排列,其最长上升子序列长A,最长下降子序列长B,求N的最大值和对应的一种解

最长可达A*B

最终子序列由A段长度为B的下降子串构成,每一段下降串的最大值递增

例如

5 2

答案
10
2 1 4 3 6 5 8 7 10 9

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int a1[maxn],a2[maxn];

int main(){
//#define test
#ifdef test
	freopen("in.txt","r",stdin);freopen("out1.txt","w",stdout);
#endif
	int a,b;
	while(cin>>a>>b){
		cout<<a*b<<endl;
		n=a*b;
		int cnt=1;
		for(int i=1;i<=a;i++){
			for(int j=i*b;j>b*(i-1);j--){
				cout<<j<<' ';
			}
		}
		cout<<endl;
	}
#ifdef test
	fclose(stdin);fclose(stdout);system("out1.txt");
#endif
	return 0;
}

  

posted @ 2018-03-27 09:54  nervending  阅读(609)  评论(0编辑  收藏  举报