XUPT_STA2018(部分题解)

作为学园都市最强的lv5,一方通行必须解决一道数学题才能接触last order身上植入的病毒,请你帮他解决这个问题。
给出两个整数a,b 求出[a,b]区间中所有整数的最大公约数。输入输入包括一行,一行中有两个数字a,b,(1《=a《=b《=10^100)输出输出一个整数,代表问题中所求的最大公约数样例
Input
1 2
Output
1
Input
61803398874989484820458683436563811772030917980576 61803398874989484820458683436563811772030917980576
Output
61803398874989484820458683436563811772030917980576

            相邻两数的最大公约数必为1,所以若输入两数相等直接输出,不相等输出1。
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string s1,s2;
	cin >> s1 >> s2;
	if (s1==s2) cout << s1;
	else cout << "1";
	return 0;
}

        B - 大霸星祭     CodeForces - 934A 

学园都市一年一度的大霸星祭开始了,现在我们把视线转移到赛场,现在正在进行的是抢灯笼比赛的现场,有来自常盘台中学的御坂美琴选手对阵……啊不好意思比赛已经开始了!
抢灯笼比赛的规则是这样的,对阵双方分别拥有N,M个灯笼,每个灯笼都有一个亮度值,其中一个人要把其中一个灯笼藏起来,而他的对手则要从自己的灯笼和对手的灯笼中个选择一个,得分是这两个灯笼亮度之积。
我们回到比赛现场,现在御坂美琴选手是藏灯笼的一方,她能否拿下决胜局赢得比赛呢?
因为一些不可告人的目的,御坂美琴必须赢得这场比赛,于是她向你求助,请你告诉她如何藏灯笼,才能让对手获得分数最小,对阵双方都会选择对自己最有利的灯笼。
Input输入第一行有两个整数n,m 代表御坂美琴和对手两个人拥有的灯笼(2《=n,m《=50)
接下来两行,第一行n个数是御坂美琴的灯笼的亮度值,第二行m个数是对手的灯笼亮度值 灯笼的亮度值的绝对值不会超过10^9Output输出对手在御坂美琴选择藏起来她选择的灯笼后能获得的最大值。Example
Input
2 2
20 18
2 14
Output
252
Input
5 3
-1 0 1 2 3
-1 0 1
Output
2
Note

第一个例子里,御坂选手藏起来 20 对手会从她那里选择18 ,然后从自己这边选择14

的二个例子中,御坂选手藏起来3然后 对手会选择 御坂选手的2和自己的1

            
            题意:从自己地方去掉一个数,对方从两堆数中各选一个数相乘,求乘积最大。注意有负数,可以先去掉最大最小的都试一下,然后从计算如何能使对方获得的最大乘积最小。

#include <cstdio>
#include <iostream>
#include <algorithm>
typedef __int64 ll;
using namespace std;
int n,m;
ll a[55],b[55];
ll s1,s2,ans=0;

int main()
{
	cin >> n >> m;
	for (int i=0;i<n;i++)
		cin >> a[i];
	for (int i=0;i<m;i++)
		cin >> b[i];
	sort(a,a+n);//a排序
	sort(b,b+m);//b排序
	s1=max(max(a[1]*b[0],a[n-1]*b[m-1]),max(a[1]*b[m-1],a[n-1]*b[0]));//去掉最小值
	s2=max(max(a[0]*b[0],a[n-2]*b[m-1]),max(a[0]*b[m-1],a[n-2]*b[0]));//去掉最大值
	ans=min(s1,s2);
	cout << ans;
	return 0;
}

        C - 初春的烦恼     CodeForces - 909A 

初春接到了风纪委员的工作指令,要求把一些能力者的名字缩写表示出来。
一个人的名字缩写,由姓氏的前缀+名字的前缀组成,这两个部分都不能为空。这样的话就让一个人会有多个缩写,很不方便。初春需要把每个人的名字缩写中,字典序最小的找出来。但是她想和朋友们一起去玩,请你帮帮她吧。
一个字符串的前缀是指从字符串的第一个位置开始的子串,比如“abcde”的前缀就有“ab,abc” 但是“bc,c”不是前缀。
如果字符串a比字符串b的字典序小,有两种情况,要么a是b的前缀,要么在a和b第一个不同的地方,a串的字符要比b串的字符在字母表的顺序靠前。Input输入一个人的名字,由两个字符串组成,中间用一个空格分隔开。姓氏,名字的长度大于1小于等于10,仅由小写英文字母组成Output输出字典序最小的缩写Example
Input
harry potter
Output
hap
Input
tom riddle
Output
tomr

            用substr可以比较轻松解决。
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

int main()
{
	string s1,s2,s3,s4,s,m=" ";
	cin >> s1 >> s2;
	for (int i=1;i<=s1.length();i++)
	{
		s3=s1.substr(0,i); //姓的前缀
		for (int j=1;j<=s2.length();j++)
		{
			s4=s2.substr(0,j); //名的前缀
			s=s3+s4; //姓名的前缀相连
			if (s<m||m==" ") m=s;
		}
	}
	cout << m;
	return 0;
}

黑子又晚归了!这次舍监并没有拧断她的脖子,而是要求她整理厨房。
厨房可以表示成N行N列的方形区域,每个格子中都有一个整数,舍监要求可怜的黑子按照如下规则整理厨房:
对于任何一个格子中数字不等于1的格子a[x][y],都能找到两个位置s,t 使得a[x][y] = a[s][y]+a[x][t]。
黑子想尽快投入姐姐大人(逃)的怀抱,于是想先判断现在的厨房是否已经满足上述条件。请你帮帮她吧~Input第一行是一个整数n (1<=n<=50) 接下来的n行n列代表每个格子中的数字。Output如果厨房是整理好的,输出“YES”否则输出“NO”Example
Input
3
1 1 2
2 3 1
6 4 1
Output
Yes
Input
3
1 5 2
1 1 1
1 2 3
Output
No
Note在第二个例子中,5不能被同一行和同一列的数字来表示
        暴力每个位置都检测一遍就行。
#include <cstdio>
#include <iostream>
using namespace std;
int a[55][55],n,flag=1,flag1=1,i,j,s,t;

int main()
{
	cin >> n;
	for (i=0;i<n;i++)
		for (j=0;j<n;j++)
			scanf("%d",&a[i][j]);
	for (i=0;i<n;i++)
	{
		for (j=0;j<n;j++)
		{
			if (a[i][j]!=1)
			{
				flag=0;
				for (s=0;s<n;s++)
				{
					for (t=0;t<n;t++)
						if (a[i][j]==a[s][j]+a[i][t])
							{flag=1; break; }
				}
			}
			if (!flag) {flag1=0; break;}
		}
		if (flag1==0) break;
	}
	if (flag1) cout << "Yes";
	else cout << "No";
	return 0;
}

        E - 御坂美琴的自制饼干     CodeForces - 799A 

“御坂学姐突然要来我家烤饼干,一定是有男朋友了,这次一定要问出来!”泪子这样想着,一边准备烤饼干的炉子。
佐天泪子家里有两个炉子,烤k个饼干需要t秒,她们要至少烤制n块饼干。第一个炉子已经预热好了,但是第二个炉子没有。第二个炉子预热需要d秒。k个饼干在t秒同时烤好,第二个炉子在预热的时候只能用第一个炉子,第二个炉子预热结束之后,两个炉子可以同时用。
因为炉子的预热很是麻烦,请你帮帮她判断应不应该用第二个炉子,泪子会选择最快的一种方案。Input四个整数n,t,k,d (1《n,t,k,d《1000)Output如果预热第二个炉子会加快这个过程输出“YES”,否则输出“NO”Example
Input
8 6 4 5
Output
YES
Input
8 6 4 6
Output
NO
Input
10 3 11 4
Output
NO
Input
4 2 1 4
Output
YES
Note在第一个例子中,一个炉子在12分钟能烤8块饼干。5分钟后第二个炉子可以使用,6秒后第一个炉子烤出来4块饼干,11分钟后第二个炉子将剩下的饼干烤完,所以预热第二个炉子更快 

第二个例子中无论使用第二个炉子与否都不会让进程加快 

第三个例子只用一个炉子3分钟可以烤11个饼干,已经达到要求,但是要使用第二个炉子反而会让时间变长,所以不需要第二个炉子
            题意:烤饼干,一个炉子可以直接用,另一个需要预热,炉子t秒k块饼干。问要不要用第二个炉子。可以直接判断一下不用第二个炉子和只用第二个炉子烤k块饼干的时间,然后看需不需要第二个炉子。
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int n,t,k,d,s1,s2;

int main()
{
	cin>>n>>t>>k>>d;
	s1=((n-1)/k+1)*t; //不用第二个炉子
	s2=max(d+t,(n-1)/k*t); //用第二个炉子烤k块饼干
	if (s1<=s2) printf("NO");
	else printf("YES");
	return 0;
}

        F - [item]的特殊任务     CodeForces - 893C 

"听说了吗?最新的都市传说!“ 学园都市有很多都市传说,有些是真的,但有些是假的。
都市传说的传播方式主要通过人们口口相传。现在你知道有N个人愿意传播都市传说,只要你支付客观的价钱。在你支付一定金钱之后,这位神秘人就会向他的朋友传播,他的朋友也向朋友的朋友传播(不要钱)……。芙兰达按照麦野的指令向这N个人传播一个都市传说(是真是假呢~),请你告诉她能完成任务的最少花费。Input第一行有两个整数n,m,代表n个人,m对朋友。(1<=n<=10^5,0<=m<=10^5)
接下来的一行有n个数,代表第i个人愿意传播都市传说所需要的钱数(0<=i<=10^9)
接下来的m行,每行有两个整数,a,b代表a,b是朋友(1<=a,b<=n,a≠b)Output输出最小的花费Example
Input
5 2
2 5 3 4 8
1 4
4 5
Output
10
Input
10 0
1 2 3 4 5 6 7 8 9 10
Output
55
Input
10 5
1 6 2 7 3 8 4 9 5 10
1 2
3 4
5 6
7 8
9 10
Output
15

            题意:给n个人传话,给每个人传话都要一定费用,一部分人是朋友,给其中一个人传话所有人都会知道这件事。问最小花费。存成一个图,然后用bfs搜索一下就行,记住是无向图,一开始因为这个wa了好几次。好像还可以用并查集,不会用,可以思考一下。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
typedef long long ll;
using namespace std;
ll n,m,x,y,mini=-1,ans=0;
ll a[100005][2];
vector<ll> v[100005];

void bfs(int i)
{
	queue<int> q;
	q.push(i);
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		if (a[now][0]<mini) mini=a[now][0];
			a[now][1]=1;
		for (int j=0;j<v[now].size();j++)
			if (!a[v[now][j]][1]) q.push(v[now][j]);
	}
}

int main()
{
	memset(a,0,sizeof(a));
	cin >> n >> m;
	for (int i=1;i<=n;i++)
		scanf("%lld",&a[i][0]);
	for (int i=1;i<=m;i++)
	{
		scanf("%lld%lld",&x,&y);
		v[x].push_back(y);
		v[y].push_back(x); //无向图记得要连回来 
	}
	for (int i=1;i<=n;i++)
	{
		if (a[i][1]) continue;
		mini=a[i][0];
		bfs(i);
		ans+=mini;
	}
	cout << ans;
	return 0;
}

并查集做法(递归)

比bfs(dfs)更快

#include <cstdio>
#include <iostream>
#define MAX_N 100005
typedef long long ll;
using namespace std;
int co[MAX_N],pre[MAX_N];
int n,m,a,b;
ll ans=0; //注意ans要用ll否则会wa

int find(int x)  //找x的根节点
{
	if (pre[x]==x)
		return x;  //前一项就是自己->找到根节点
	else 
		return pre[x]=find(pre[x]);   //往前找一项
}

void inline combine(int p,int q)
{
	int x=find(p),y=find(q); //x为p的根节点,y为q的根节点
	if (x==y) return;  //在一棵树上不做任何操作
	if (co[x]>co[y])   //x树的花费大于y树的花费
		pre[x]=y;    //将x树的根节点加入为y树的根节点的子节点,即将x,y合并为一棵树
	else pre[y]=x;    //同理
}

int main()
{
	cin >> n >> m;
	for (int i=1;i<=n;i++)
	{
		pre[i]=i;  //一开始所有的树根节点都是自己
		scanf("%d",&co[i]);
	}
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		combine(a,b);
	}
	for (int i=1;i<=n;i++)
		if (pre[i]==i) ans+=co[i];   //ans加根节点为自身的花费
	cout << ans;
	return 0;
}

G - 上条当麻的暑假作业 CodeForces - 902B 

 “我的暑假作业可怎么办啊……真不幸”上条当麻的暑假作业还有很多。但他还要忙着拯救世界(喂食index)请你帮他做一道吧, 小萌老师可不好惹。
题目给出一颗有根树,请你输出将这棵树上每个节点v染成对应的颜色Cv,所需要的最少的操作。这棵树的树根是节点1,标号从1到n
染色操作是这样的,选择一个节点v和颜色x,一次染色操作会把节点v所在的子树的所有节点都染成x。
树的定义:https://baike.baidu.com/item/%E6%A0%91/2699484?fr=aladdin&fromid=12062173&fromtitle=%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84+%E6%A0%91Input第一行是一个整数n代表树的节点个数(2<=n<=10^4)
第二行有n-1个整数p2,p3…pn(1《=pi《i),代表i节点和pi有一条边
第三行有n个整数c1,c2,c3,…cn 代表每个节点需要被染成的颜色
保证数据是一个合法的树Output输出最小的步骤Example
Input
6
1 2 2 1 5
2 1 1 1 1 1
Output
3
Input
7
1 1 2 3 1 4
3 3 1 1 1 2 3
Output
5
Note

这是第一个例子的图

第一步我们把节点1的子树染色成颜色2(数字代表颜色):

下一步我们将节点5的子树变成颜色1

第三步染色节点2:

题意:一开始没看懂这个树是怎么输入的,结束后仔细看发现是从1开始,然后第二行是后面每个节点的父节点,第三行是最后要涂成的颜色。这个题看了大神的做法,其实有一个比较方便的方法,就是遍历颜色,如果某节点颜色和父节点一样说明只需操作父节点即可,而如果颜色不一样说明这个节点也需要操作,则操作数+1。也可以用dfs搜索,麻烦又耗时。以下为第一种方法的代码。
#include <cstdio>
#include <iostream>
#define MAX_N 10005
using namespace std;
int a[MAX_N],b[MAX_N];
int n,cnt=0;

int main()  
{    
	cin >> n; 
	for(int i=2;i<=n;i++)  
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)  
		scanf("%d",&b[i]); 
	for(int i=1;i<=n;i++)  
		if(b[i]!=b[a[i]])  
 			cnt++;  
	cout << cnt << endl; 
	return 0;  
}

        I - 御坂美琴的噩梦     HDU - 5914 


“只要我摧毁了这个工厂,实验就不会进行了吧……”
学园都市排名第三的Lv5,【超电磁炮】御坂美琴站在一座秘密工厂的房顶上,准备潜入。
“我首先要破解这里的安保系统,可恶……这是什么问题嘛”
工厂的安保系统要求接入者解决这个问题:有一个数列1,2,3,4,5,…,n,现在要求从这个数列中删除最小个数的数字,使得剩下的任何三个数都不能形成三角形。 
请你帮助御坂美琴,结束她的噩梦Input第一行有一个整数T,代表T组测试样例 接下来T行,每行有一个整数(1《n《20)Output输出“Case #x: y“代表第x个测试样例的结果是y,占一行Sample Input
3
4
5
6
Sample Output
Case #1: 1
Case #2: 1
Case #3: 2

        题意:题意很明显,满足这个条件的数列为1,2,3,5,8,13,21。由于数据范围较小可以直接打表。
#include <cstdio>
#include <iostream>
using namespace std;
int t,n,cnt=0;
int a[25]={0,0,0,0,1,1,2,3,3,4,5,6,7,7,8,9,10,11,12,13,14};

int main()
{
	cin >> t;
	while (t--)
	{
		cin >> n;
		printf("Case #%d: %d\n",++cnt,a[n]);
	}
	return 0;
}

        

        K - 一方通行和最大公约数II     CodeForces - 798C 

一方通行,学院最强的Lv5,在被“幻想杀手“上条当麻制裁(友情破颜拳)之后,变成了萝莉控……
“来和我玩游戏吧,御坂御坂用期待的口气说道“
“好吧,就陪你玩一会”
“last order想让一个数组的最大公约数超过1,她可以进行一个操作,选定一个  i(0<= i<=n),将a[i],a[i+1]替换成a[i]-a[i+1],a[i]+a[i+1],顺序不变,请问她最少能用多少次操作就能达成目的?或者告诉她不可能达到。Input第一行是一个整数n,代表有n个数(2<=n<=100 000)
下面一行有n个数,代表数字ai(1<=ai<=10^9)Output如果可以让数组的最大公约数超过1输出“YES”,下一行输出最小操作次数。 如果不能,输出“NO”Example
Input
2
1 1
Output
YES
1
Input
3
6 2 4
Output
YES
0
Input
2
1 3
Output
YES
1

            题意:让一个数列的最大公约数大于1,可以让这个数列都变成偶数。这里有一个操作a[i],a[i+1]替换成a[i]-a[i+1],a[i]+a[i+1]。即为两偶不用换,两奇换一次,一奇一偶换两次。
            注意:换完之后最后一个数可能仍为奇数需要额外判断。如果一开始最大公约数就大于1直接输出0。
#include <cstdio>
#include <iostream>
using namespace std;
int n,a[1000005],sum=0,t;

int gcd(int a,int b) //求最大公约数
{
	int t;
	while(b)
	{
		t=b;
		b=a%b;
		a=t;
	}
	return a;
}

int main()
{
	cin >> n;
	for (int i=0;i<n;i++)
		scanf("%d",&a[i]);
	t=a[0];
	for (int i=1;i<n;i++)
	{
		t=gcd(t,a[i]);
	}
	if (t>1) {cout << "YES" << endl << "0"; return 0;} // 一开始最大公约数大于1直接输出0
	for (int i=0;i<n-1;i++)
	{
		if (a[i]%2)
		{
			if (a[i+1]%2) sum++;
			else sum+=2;
			a[i]=a[i+1]=2; // 将两个数置为偶数(只要置为偶数就行)
		}
	}
	if (a[n-1]%2) sum+=2;  // 最后仍为奇数的情况
	cout << "YES" << endl << sum;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值