2017杭电ACM集训队单人排位赛 - 1(ALL题解)

A. 看日出

看日出

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
你知道的,人悲伤地时候就会想看日落,但往往一个人一天只能看一次日落。
在地球上美国正午时分时,法国正夕阳西下,因此如果你在美国看完日落后一分钟内赶到法国就可以再看一次日落。
Thirty很喜欢看日落,但和地球伤的人不同,他住在一个比他自己大不了多少的星球上,每次他看完一次日落想再看一次的时候,他只需要把你的椅子往前挪一段距离就可以了。
现在Thirty正坐在他星球的赤道上,赤道可以被视为一个圆,周长为m米,每次看完日落后,他都会将椅子沿着赤道往前挪动n米,再看一次日落,Thirty决定,他会一直这样重复他看日落的过程,直到他回到他第一次看日落的地方。
那么问题来了,一直赤道的周长m米和椅子每次挪动的距离n米,你能算一下Thirty总共看了多少次日落吗?(回到起点的那一次不算)
 

Input
输入数据包含多个样例,每个样例包含一组输入。
一个输入包含两个正整数n,m, n,m不超过 104
 

Output
输出Thirty看日落的次数。
 

Sample Input
  
  
1 3 18
 

Sample Output
  
  
6
 

水题。。就是问你挪多少次可以挪回原点,答案就是Lcm(n, m)/n

#include<stdio.h>
int Gcd(int a, int b)
{
	if(a%b==0)
		return b;
	return Gcd(b, a%b);
}
int main(void)
{
	int T, n, m, t;
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d%d", &n, &m);
		t = n/Gcd(n, m)*m;
		printf("%d\n", t/n);
	}
	return 0;
}


B. 光头强选举

光头强选举

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
光头强非常渴望权利。他想赢得即将到来的选举。
现在有n个候选人,包括光头强,其中光头强是一号候选人。我们现在已经知道每个候选人获得了多少张选票。其中第i个候选人拥有 ai 张选票。为了赢得选举,光头强的得票数必须严格大于其他候选人。
胜利比一切都重要,所以光头强决定通过作弊来赢得选举。他会通过贿赂将给其竞争者投票的选民将选票改投给自己。那么光头强最少要贿赂几个选民才能获得选举的胜利?
 

Input
输入数据包含多个测试实例,每个测试实例的第一行有整数 n (2  n   100),表示有n个候选人。
接下来1行有n个数  a1  ,  a2  ,...  an  (1  ai  1000)表示每个候选人的票数。
 

Output
对于每个测试实例,输出最少要贿赂几个人才能使光头强赢得选举(他的得票数严格大于其他所有候选人)
 

Sample Input
  
  
4 1 8 8 8 5 5 1 11 2 8
 

Sample Output
  
  
6 4

还是水题。。。超级暴力,每次O(n)遍历找票最多的那个人,然后贿赂,直到光头强的票最多

注意要严格最大,所以每次找最大值的时候记得是>=不是>

#include<stdio.h>
int main(void)
{
	int n, i, a[105], ans, temp, bet;
	while(scanf("%d", &n)!=EOF)
	{
		ans = 0;
		for(i=1;i<=n;i++)
			scanf("%d", &a[i]);
		while(1)
		{
			temp = 1, bet = a[1];
			for(i=2;i<=n;i++)
			{
				if(a[i]>=bet)
					bet = a[i], temp = i;
			}
			if(temp==1)
				break;
			ans++;
			a[temp]--, a[1]++;
		}
		printf("%d\n", ans);
	}
	return 0;
}


C. yyf和女朋友玩游戏

yyf和女朋友玩游戏

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
yyf找到女朋友之后和女朋友玩起了网游。这天他打了三把武器给自己的女朋友,武器有8个属性,每个属性是一个正整数,最多为99,yyf想选一把最厉害的武器送给自己的女朋友,设第一把武器的属性为 a1a8 ,第二把武器的属性为 b1b8 ,若第一把武器比第二把武器厉害,则 a1=b1,a2=b2....ai1=bi1,ai>bi , 1 i =8, 请输出最厉害的武器的编号,第一把为1,第二把为2,第三把为3;由于ffy是第一次打武器,所以他打出武器的单属性最低是0。
 

Input
输入数据包含多个测试实例,每个测试实例中:
第一行8正整数,第一把武器8个的属性。
第二行8正整数,第二把武器8个的属性。
第三行8正整数,第三把武器8个的属性。
 

Output
一个数,表示最厉害的武器的编号。若有多个选择则输出编号小的那个。
 

Sample Input
  
  
10 10 10 10 10 10 10 9 10 10 10 10 10 10 9 10 10 10 10 10 10 9 10 10 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99
 

Sample Output
  
  
1 1
 

然后还是水题。。。。翻译过来就是给你三个序列,问哪个序列的“字典序“最大

如果都一样大输出编号最小的那个

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef struct
{
	int p[12];
}Res;
Res a, b, c;
int Jud(Res a, Res b)
{
	int i;
	for(i=1;i<=8;i++)
	{
		if(a.p[i]>b.p[i])
			return 1;
		if(a.p[i]<b.p[i])
			return 2;
	}
	return 1;
}
int main(void)
{
	int i;
	while(scanf("%d", &a.p[1])!=EOF)
	{
		for(i=2;i<=8;i++)
			scanf("%d", &a.p[i]);
		for(i=1;i<=8;i++)
			scanf("%d", &b.p[i]);
		for(i=1;i<=8;i++)
			scanf("%d", &c.p[i]);
		if(Jud(a, b)==1 && Jud(a, c)==1)
			printf("1\n");
		else if(Jud(b, a)==1 && Jud(b, c)==1)
			printf("2\n");
		else
			printf("3\n");

	}
	return 0;
}


D. 离开迷宫

离开迷宫

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
yyf是一个日理万机的男人,但自从最近他勾搭上了女神之后便随叫随到,以至于荒废了很多事情。这天,yyf正在探索一个充满陷阱的古代迷宫,他的女神来电话了,由于离迷宫出口太远了,可能要花很多时间才能回去,所以yyf不打算原路返回,而是挥动他那强壮有力的右手砸开墙壁直接走向出口。已知yyf在(1,1)的位置,而出口在(N,M)的位置,yyf每次只会向下或向右走。
而同时又由于事发突然,yyf没能给女神准备礼物,于是他决定在回去的路上尽量多拿点迷宫里的财宝作为礼物。当然,古代的迷宫里少不了陷阱,虽然yyf实在太强了而导致所有的陷阱只能对他的装备造成1点的耐久损失,但由于yyf本来只是打算探索迷宫,所以并没有准备太好的装备,最初的耐久值仅为x,而如果装备破破烂烂的走到女神那边是非常有失风度的。所以yyf想要知道自己能否在保证最快离开迷宫的同时装备不被破坏(耐久=0时装备会破破烂烂哦),如果可以,他希望能带走尽量多的财宝,如果不行,他就只能在离开迷宫后回趟家带上自己最好的衣服和专门为女神准备的礼物了。
给你迷宫里分布着的财宝信息以及陷阱布置。yyf希望知道自己在保证装备不变成破破烂烂的情况下最多能拿多少的财宝,如果出现多个方案,yyf希望自己的装备能尽量少被陷阱打中。
 

Input
第一行:迷宫的大小N和M以及yyf的装备的耐久x 
接下来2N行
前N行每行M个整数(),表示迷宫里(i,j)位置的财宝价值
后N行每行M个数字0或1,表示迷宫里(i,j)位置是否有陷阱(1为有)
(0<=N,M,x<=100)
 

Output
若有可行方案,输出在获得最大价值的情况下装备能留有的最大耐久度与可获得的财宝的最大价值。若无可行方案,则输出-1。
 

Sample Input
  
  
3 3 4 1 2 9 2 6 2 3 2 1 1 1 1 0 1 0 0 0 1
 

Sample Output
  
  
1 12

多一维的dp,dp[i][j][k]表示当前走到第i行第j列,护甲值还剩k能取到的最大价值

转移:dp[i][j][k] = max(dp[i-1][j][k], dp[i][j-1][k])+a[i][j];(无陷阱)

dp[i][j][k] = max(dp[i-1][j][k+1], dp[i][j-1][k+1])+a[i][j];(有陷阱)

注意边界处理,可以初始化dp数组为一个很小的负数,然后先把dp[1][1][x]求出来再转移

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[105][105], x[105][105], dp[105][105][105];
int main(void)
{
	int n, m, i, j, p, k, bet, ans;
	while(scanf("%d%d%d", &n, &m, &p)!=EOF)
	{
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=m;j++)
				scanf("%d", &a[i][j]);
		}
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=m;j++)
				scanf("%d", &x[i][j]);
		}
		memset(dp, -60, sizeof(dp));
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=m;j++)
			{
				if(i==1 && j==1)
				{
					dp[i][j][p-x[i][j]] = a[i][j];
					continue;
				}
				for(k=1;k<=p;k++)
				{
					if(x[i][j]==0)
						dp[i][j][k] = max(dp[i-1][j][k], dp[i][j-1][k])+a[i][j];
					else
						dp[i][j][k] = max(dp[i-1][j][k+1], dp[i][j-1][k+1])+a[i][j];
				}
			}
		}
		bet = -6000000;
		for(k=1;k<=p;k++)
		{
			if(dp[n][m][k]>=bet)
				bet = dp[n][m][k], ans = k;
		}
		if(bet==-6000000)
			printf("-1\n");
		else
			printf("%d %d\n", ans, bet);
	}
	return 0;
}


E. yyf倒水

yyf倒水

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
yyf和他女朋友到一家饭店吃饭,饭店里的服务员给yyf和女朋友每人一个杯子并把一个水壶放在了一边。女朋友想喝饮料,从饭店冰箱里拿来了一瓶“小茗同学”。倒满两个杯子后,yyf忍不住喝了一口,十分惬意。女朋友把两个杯子放在一起,认真地看了杯子里的水,向yyf问道,假设第一个杯子的容量是A升,第二个杯子的容量B升,两个杯子一开始都为空,现在有三个操作,1.FILL(i):将i杯子中的饮料倒满。2.EMPTY(i):将i杯子中的饮料全部倒出只剩空瓶子。3.POUR(i,j)将杯子i中的水倒到杯子j中,若杯子 j 满了或者杯子i已经为空了则停止。如果你每次只能进行上面操作中的一种,你能在最少操作数内使其中一个杯子的饮料容量恰好为C吗?看着女朋友坚定的眼神,yyf陷入了深思,过了几秒,yyf发现自己已经能理论解决这个问题了,但是无奈没有电脑,所以向你求助,聪明的你,能帮助yyf回答这个问题吗?
 

Input
输入包含三个数A,B,C,三个数保证是整数且范围都是在[1,100]内,C<=max(A,B)
 

Output
如果能到达目标输出第一行包含一个整数k表示到达目标水量最少需要操作的步骤数。如果不能到达目标则输出“impossible”(没有双引号)。
 

Sample Input
  
  
3 5 4 3 100 64
 

Sample Output
  
  
6 24

广搜,每次有六种状态:倒空*2,倒满*2,转移*2

vis[x][y]表示状态为第一个杯子xL,第二个杯子yL

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct
{
	int x;
	int y;
}Res;
Res temp, now;
queue<Res> q;
int dp[105][105], vis[105][105];
int main(void)
{
	int A, B, C;
	while(scanf("%d%d%d", &A, &B, &C)!=EOF)
	{
		memset(dp, -1, sizeof(dp));
		memset(vis, 0, sizeof(vis));
		while(q.empty()==0)
			q.pop();
		dp[0][0] = 0;
		vis[0][0] = 1;
		now.x = now.y = 0;
		q.push(now);
		while(q.empty()==0)
		{
			now = q.front();
			q.pop();
			vis[now.x][now.y] = 0;
			if(now.x==C || now.y==C)
				break;
			if(dp[A][now.y]==-1)
			{
				dp[A][now.y] = dp[now.x][now.y]+1;
				if(vis[A][now.y]==0)
				{
					temp.x = A, temp.y = now.y;
					q.push(temp);
					vis[A][now.y] = 1;
				}
			}
			if(dp[now.x][B]==-1)
			{
				dp[now.x][B] = dp[now.x][now.y]+1;
				if(vis[now.x][B]==0)
				{
					temp.x = now.x, temp.y = B;
					q.push(temp);
					vis[now.x][B] = 1;
				}
			}
			if(dp[0][now.y]==-1)
			{
				dp[0][now.y] = dp[now.x][now.y]+1;
				if(vis[0][now.y]==0)
				{
					temp.x = 0, temp.y = now.y;
					q.push(temp);
					vis[0][now.y] = 1;
				}
			}
			if(dp[now.x][0]==-1)
			{
				dp[now.x][0] = dp[now.x][now.y]+1;
				if(vis[now.x][0]==0)
				{
					temp.x = now.x, temp.y = 0;
					q.push(temp);
					vis[now.x][0] = 1;
				}
			}
			temp.x = now.x-min(now.x, B-now.y);
			temp.y = now.y+min(now.x, B-now.y);
			if(dp[temp.x][temp.y]==-1)
			{
				dp[temp.x][temp.y] = dp[now.x][now.y]+1;
				if(vis[temp.x][temp.y]==0)
				{
					q.push(temp);
					vis[temp.x][temp.y] = 1;
				}
			}
			temp.y = now.y-min(now.y, A-now.x);
			temp.x = now.x+min(now.y, A-now.x);
			if(dp[temp.x][temp.y]==-1)
			{
				dp[temp.x][temp.y] = dp[now.x][now.y]+1;
				if(vis[temp.x][temp.y]==0)
				{
					q.push(temp);
					vis[temp.x][temp.y] = 1;
				}
			}
		}
		if(now.x!=C && now.y!=C)
			printf("impossible\n");
		else
			printf("%d\n", dp[now.x][now.y]);
	}
	return 0;
}


F. yyf之贪吃蛇大作战

没写。。感觉是个很麻烦的模拟



G. 吃巧克力

吃巧克力

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
CYF 喜欢吃巧克力,有一天,CYF收到了一份镶嵌在平面直角坐标系上的巧克力,这个巧克力的形状是一个正多边形。日子一天天过去,CYF吃完了这份巧克力,但是却忘记了自己吃的巧克力有几条边,只记得正多边形巧克力上三个点的坐标。
CYF知道送自己巧克力的人非常小气,所以正多边形巧克力的边数不会超过100。现在的CYF非常想知道自己吃的正多边形巧克力到底有多少条边,你能帮他算一下吗?
 

Input
每个样例包含一组输入。
一个输入有三行每行是一个点的坐标
Xi   Yi
坐标之间用空格隔开
 

Output
输出CYF吃的巧克力最少有多少个角
 

Sample Input
  
  
0.000000 0.000000 1.000000 1.000000 0.000000 1.000000
 

Sample Output
  
  
4

这题的三个点连起来是个三角形,

先求出三角形的外接圆半径

三角形面积用海伦公式S = sqrt(C/2*(C/2-L1)*(C/2-L2)*(C/2-L3)),其中L1, L2, L3为三边长

那么外接圆半径就是L1*L2*L3/(4*S)

之后就可以得出三角形三条边连接圆心的三个圆心角度数G1, G2, G3

答案就是2π/Gcd(G1, G2, G3)

#include<stdio.h>
#include<string.h>
#include<math.h>
typedef struct
{
	double x;
	double y;
}Point;
Point a, b, c;
double Len(Point a, Point b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double DGcd(double a, double b)
{
	if(a<0.01)
		return b;
	if(b<0.01)
		return a;
	return DGcd(b, fmod(a, b));
}
int main(void)
{
	double L1, L2, L3, S, C, R, G1, G2, G3, T;
	while(scanf("%lf%lf%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y, &c.x, &c.y)!=EOF)
	{
		L1 = Len(a, b);
		L2 = Len(b, c);
		L3 = Len(a, c);
		C = L1+L2+L3;
		S = sqrt(C/2*(C/2-L1)*(C/2-L2)*(C/2-L3));
		R = L1*L2*L3/(4*S);
		G1 = acos((2*R*R-L1*L1)/(2*R*R));
		G2 = acos((2*R*R-L2*L2)/(2*R*R));
		G3 = acos((2*R*R-L3*L3)/(2*R*R));
		T = DGcd(G1, G2);
		T = DGcd(T, G3);
		printf("%.0f\n", 2*acos(-1.0)/T);
	}
	return 0;
}


H. yyf的家庭影院

yyf的家庭影院

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
yyf是全机房最有钱的土豪,独自拥有一个家庭影院。有一天yyf想要请他的女朋友们(如:椎名真白,雪之下雪乃,宫园薰,以及楪祈等等)一起看新出的电影,于是花重金购买了《kimi no na wa》。
yyf的女朋友们对椅子的扶手有特别的要求。有的要有左边的扶手用才开心,有的要有右边的扶手用才开心,有的要两边的扶手都给自己用才开心,还有一些觉得扶手无所谓,只要能到yyf家看电影就很开心(吃惊!)。
yyf的家庭影院的座位只有一排N个位置(电影院中两个相邻的位置之间是共用一个扶手)。现在yyf想要邀请尽可能多的女朋友来家中看电影,并且使她们感到开心,从而增加对自己的好感度。由于yyf忙于肝阴阳师,就花重金来请你来计算,他可以最多邀请几位女朋友一起来看这部电影。
 

Input
第一行输入一个N,代表家庭影院的位置数目;
第二行输入四个整数:a,b,c,d。代表yyf有a个喜欢左边扶手的女朋友,b个喜欢右边扶手的女朋友,c个同时喜欢左右两个扶手的女朋友,d个只要和来yyf家看电影就很开心的女朋友。
其中N,a,b,c,d均在1~ 1010
 

Output
本场电影yyf最多可以邀请多少个女朋友。
 

Sample Input
  
  
10 2 2 4 2 10 10 10 10 10
 

Sample Output
  
  
9 10

所有扶左手的女生全部坐左边,所有扶右手的女生全部左右边

然后中间的位置,扶两边扶手的和不扶扶手的女生交替坐

#include<stdio.h>
#include<algorithm>
using namespace std;
int main(void)
{
	__int64 n, a, b, c, d, x;
	while(scanf("%I64d%I64d%I64d%I64d%I64d", &n, &a, &b, &c, &d)!=EOF)
	{
		if(a+b>=n)
			printf("%I64d\n", n);
		else
		{
			x = n-a-b;
			printf("%I64d\n", min(n, min((x+1)/2, c)+d+a+b));
		}
	}
	return 0;
}


I. 来自星星的祝福

来自星星的祝福

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
在一个遥远的山区中,流传着一个传说,一个真正的好男人,需要受到来自M个不同星座的女孩子的赞美--“你是个好人”,才会找到真爱。
毫无疑问,yyf就是这样的好男人。他费尽千辛万苦,找到了瞎子算命师ZJiaQ,ZJiaQ告诉他:你这辈会受到n个女孩子的赞美。
那么,请问yyf找到真爱的概率有多少?
假设每个女孩子是M个星座中任一个的概率相等。
 

Input
第一行一个数T(T<=10),表示数据组数。(T可输入多次)
接下来每组数据中,输入n与m(n<=1000000000000000000(18个零),m<=100)。
 

Output
输出概率的百分比,并且不需要输出小数点后的数字。
 

Sample Input
  
  
2 1 1 2 2
 

Sample Output
  
  
%100 %50

题目可以转化为n个小球放进m个盒子中,每个盒子至少一个小球的概率

先求出情况数

容斥:答案就是m个盒子随便放 - 其中一个盒子留空(m-1)个盒子随便放 

其中两个盒子留空(m-2)个盒子随便放 - … -/+所有球全放其中一个盒子里

最后总情况数(分母)为m^n,所以答案就是


其中右半部分用快速幂,左半部分组合数每次暴力就好了

答案是浮点数要尽一切可能优化精度,很显然右边是越乘越小的,左边组合数是越乘越大的

所以当乘到一个很小的数时就让他乘左边的组合数,乘到一个很大的数就继续乘右边

如果中间过程答案特别小,直接返回0

(还有这题是四舍五入,题目中说省掉小数部分。。一不小心wa了15发)

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
double Run(__int64 n, __int64 m, __int64 k)
{
	double x, ans, a, b;
	a = m, b = 1;
	x = 1-1.0*k/m;
	ans = 1;
	while(n)
	{
		if(n%2==1)
		{
			ans = ans*x;
			while(ans<1000000000 && b<=k)
			{
				ans = ans*(a/b);
				a--, b++;
			}
			if(ans<0.00000001)
				return 0;
		}
		x = x*x;
		n /= 2;
	}
	while(b<=k)
	{	
		ans = ans*(a/b);
		a--, b++;
	}
	return ans;
}
int main(void)
{
	__int64 T, n, m, i;
	double ans;
	while(scanf("%I64d", &T)!=EOF)
	{
		while(T--)
		{
			ans = 1;
			scanf("%I64d%I64d", &n, &m);
			if(n<m)
				printf("%%0\n");
			else if(m==1 || m==0)
				printf("%%100\n");
			else if(n>=123456)
				printf("%%100\n");
			else
			{
				for(i=m-1;i>=1;i--)
				{
					if(i%2==0)
						ans += Run(n, m, i);
					else
						ans -= Run(n, m, i);
				}
				if(ans<0 || ans>10)  ans = 0;
				printf("%%%.0f\n", ans*100);
			}
		}
	}
	return 0;
}



J. LJZ的ACM协会后援团

LJZ的ACM协会后援团

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
ljz是acm协会的会长,众所周知,只有最帅的人才能当会长,ljz在进入协会的第一天就被学长看中,经过交易后不负众望成为了会长。长得帅自然会有人喜欢,所以ljz身边总是围绕着一大堆学弟,这让他很困扰,他要从其中挑出一个成为自己的心腹?现在有有n个学弟,每个学弟身上都有一个值Ai,若Ai能分解成一个素数和一个合数(都大于0)的和,则能为该学弟增加一点魅力值,不同的方案都会提供一点魅力值。例如一个学弟的Ai为11,那么11=2+9、11=3+8、11=5+6、11=7+4,那么他的魅力值为4。现在要求出这n个学弟的魅力值。
 

Input
第一行先给出总人数n<=100.第2行至n+1行每一行都有一个值2<= Ai <=1000。会输入多个n
 

Output
输出总共为n行,每一行输出 Ai 对应的魅力值。
 

Sample Input
  
  
3 5 8 11
 

Sample Output
  
  
0 1 4

水题。。只要会判断质数就好了,暴力吧

#include<stdio.h>
#include<string.h>
int a[105], ans[105], k[1005] = {-1,1};
int main(void)
{
	int n, i, j;
	for(i=2;i<=1000;i++)
	{
		if(k[i])
			continue;
		for(j=i*i;j<=1000;j+=i)
			k[j] = 1;
	}
	while(scanf("%d", &n)!=EOF)
	{
		memset(ans, 0, sizeof(ans));
		for(i=1;i<=n;i++)
			scanf("%d", &a[i]);
		for(i=1;i<=n;i++)
		{
			for(j=2;j<=a[i]-2;j++)
			{
				if(k[j]==0 && k[a[i]-j]==1)
					ans[i]++;
			}
		}
		for(i=1;i<=n;i++)
			printf("%d\n", ans[i]);
	}
	return 0;
}



K. 魔法王国

魔法王国

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
小Z是一位善良的神,他管辖的区域有n个单位面积那么大。其中有两个王国,J国与Q国。在一开始的时候,J国的疆域有x,Q国的疆域有y(x+y=n)。作为一个善良的神,小Z希望这两个国家的疆域能够保持平衡。于是,在每年的开端,他都会施展魔法,令疆域较小的那个国家疆域翻倍(若相等,则令J国疆域翻倍),相应的,另一个国家会减小。
请问经过了m年之后,两个国家的疆域为多大。
 

Input
第一行一个数T(T<=10000),表示数据组数。(T可多次输入。)
对于每组数据输入四个整数n,m,x,y含义如题所示。其中2<=n<=1 000 000 000, 1<=m<=1 000 000 000,0<=x,y<=n。x+y=n.
 

Output
对于每组数据,从大到小输出两个整数。表示m年之后两个国家的疆域大小。
 

Sample Input
  
  
1 100 1 30 70
 

Sample Output
  
  
60 40

这道题很有意思,每次将面积小的城池×2,然后让另一个城池拿n减去乘后的面积

"翻译"过来就是先×2,再取模!

所以这题就是让你求2的m次方对n取模

答案就是x*2^m%n和n-x*2^m%n,注意x是一开始面积小的那个

还有题目要求从大到小输出

#include<stdio.h>
#include<algorithm>
using namespace std;
__int64 Pow(__int64 x, __int64 y, __int64 mod)
{
	__int64 ans;
	ans = 1;
	while(y)
	{
		if(y%2==1)
			ans = ans*x%mod;
		x = x*x%mod;
		y /= 2;
	}
	return ans;
}
int main(void)
{
	__int64 T, n, m, x, y;
	while(scanf("%I64d", &T)!=EOF)
	{
		while(T--)
		{
			scanf("%I64d%I64d%I64d%I64d", &n, &m, &x, &y);
			if(x>y)  swap(x, y);
			x = x*Pow(2ll, m, n)%n;
			y = n-x;
			if(x<y)  swap(x, y);
			printf("%I64d %I64d\n", x, y);
		}
	}
	return 0;
}



L. YYF和女朋友玩游戏(2)

YYF和女朋友玩游戏

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
在若干年后,yyf终于找到了女朋友。这天yyf和他的女朋友在玩积木游戏,现在这里有x个1×1的小正方体,由这些小正方体可以组成一些“建筑”,现在他的女朋友有一个问题,告诉你这个建筑的主视图和左视图问你,问你这个建筑最少是由多少个小正方体组成的?
 

Input
第一行包含两个数字 n,m 表示主视图的列数和左视图的列数,1≤n,m≤10。
第二行包括n个数字, hi 表示主视图每一列的高度, 1≤ hi ≤20。
第三行包括m个数字, hi ’表示左视图每一列的高度, 1≤ hi ’≤20。
 

Output
输出一个整数 – 构成这个“建筑”的最少的正方体个数。
 

Sample Input
  
  
5 5 1 2 3 4 5 1 2 3 4 5
 

Sample Output
  
  
15
 

这里题解说得很对就用这个了

可以先想如何形成正视图或侧视图,那么就是二维平面,正视图(侧视图)上有多少个正方形就是有多少个正方体,然后在这个基础上侧视图(正视图)如果出现新的列(之前视图不相等)的,就要新摆放一个,否则通过平移可以看做同一列,就不需要添加正方体了,那么可以得出,最少数量正方体就是正视图或侧视图中正方形多的那个视图,把它上面的正方形数量加上另一个视图上没有出现过的所有列就是最终解。

#include<stdio.h>
int a[15], b[15];
int main(void)
{
	int n, m, i, j, ans;
	while(scanf("%d%d", &n, &m)!=EOF)
	{
		ans = 0;
		for(i=1;i<=n;i++)
		{
			scanf("%d", &a[i]);
			ans += a[i];
		}
		for(i=1;i<=m;i++)
		{
			scanf("%d", &b[i]);
			ans += b[i];
		}
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=n;j++)
			{
				if(a[i]==b[j] && a[i]!=-1)
				{
					ans -= a[i];
					a[i] = b[j] = -1;
				}
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}


M. 分西瓜

分西瓜

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
一个炎热的夏天,A和他的朋友B决定去买一个西瓜。他们选择了最大和最成熟的一个西瓜,这个西瓜重K公斤。买了西瓜以后他们马上冲回家,感到非常的口渴,决定分西瓜,但是他们面临着一个难题。
A和B都非常喜欢偶数,因此他们想分西瓜以这种方式:分出来的两个西瓜的重量都是偶数,但并不要求两个西瓜是一样重的。A和B现在都非常的累,想尽快吃西瓜,你现在的任务是帮助他们分析是否能够按照他们的要求分西瓜。当然两个人都要分到西瓜。
 

Input
输入数据包含多个测试实例,每个测试实例有一个整数 w(1<=w<=100) 表示西瓜的重量
 

Output
如果可以把西瓜按要求分为两部分就输出YES,否则输出NO
 

Sample Input
  
  
8
 

Sample Output
  
  
YES

只要是n大于2的偶数就可以

#include<stdio.h>
int main(void)
{
	int n;
	while(scanf("%d", &n)!=EOF)
	{
		if(n!=2 && n!=0 && n%2==0)
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值