2015_4_12


==题目地址==


本周出现了博弈论,,嗯,这个方面我是空白的==

A.特殊的质数肋骨

既然是要每节肋骨都是质数,可以看出一些很明显的规律,比如说是

最后一个数字如果是2的倍数肯定就不行,所以顶多才5^8个可能可行的数

dfs暴力枚举每个长度的最后一个位置的数即可

#include<stdio.h>
#include<math.h>
int a[4]={1,3,7,9};
int ch(long asd)
{
	for (long i=2;i<=(long)sqrt((double(asd)));i++)
		if (asd%i==0) return 0;
	return 1;
}
int dfs(int as,long ad)
{
	if (as==1)
		for (int i=0;i<4;i++)
			if (ch(ad*10+a[i])) printf("%ld\n",ad*10+a[i]);
	for (int i=0;i<4;i++)
		if ((ch(ad*10+a[i])))
			dfs(as-1,ad*10+a[i]);
	return 0;
}
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		if (n==1) printf("2\n3\n5\n7\n");
		dfs(n-1,2);
		dfs(n-1,3);
		dfs(n-1,5);
		dfs(n-1,7);
	}
	return 0;
}

B.简单博弈

可以看出如果n<=5必胜,因为A一定会选择全部扔完

而n=6的时候必败,因为A先手肯定扔不完,而后手的情况则进入了必胜状态

在6<n<12的时候,A先手肯定是会选择扔n-6块石头,使B进入必败的状态

而n=12时无论A怎么选择B都会进入必胜状态

由此可以轻松的发现当n=6*k时一定是必败的状态

而n=6*k+i (0<i<6)一定必胜

#include <bits/stdc++.h>
using namespace std;
int main()
{
	//freopen("F:\\TestFiles\\test.in","r",stdin);
	//freopen("F:\\TestFiles\\test2.out","w",stdout);
	int n;
	while(~scanf("%d",&n)){
		if (n%6==0){
			printf("do not escape after school!\n");
		} else printf("ha ha!!!\n");
	}
	return 0;
}


C.复杂博弈

其实这题初看不会做

后来网上查了下,这是楼教主男人8题之一

首先你可以发现当n==1时,这是必胜状态,因为先手的人可以一次全部扔完嘛

当n==2时,如果a==b,可以发现无论先手的人做什么选择,后手的人只要完全模仿先手的人,保持a==b,那么先手的人必败

而如果a<b,那么先手的人可以使得2堆满足a==a的必败状态,使得后手的人必败

当n==3时,如果a==b==c,那么先手的人,可以扔光一堆,那么状态就转换成a==b的必败状态了,如果是a==b,c同样满足,如果a,b,c互不相等,就可以发现我可以用c去填补a使得b,b,0的状态,依然是必败状态

当n==4时,如果是a==b==c==d,或者,a==b,c==d可以发现这是必败的状态,后手只要完全模仿先手的行为就可以必胜了

如果是a==b,c,d或者a,b,c==d,这种情况,先手可以把这个转换成为必败态,所以这是必胜利状态

如果是a,b,c,d,一定会有d-a>c-b,所以一定可以转移至a,c,c,a的情况,又转移至必败的状态

对于n=2k-1,或者n=2k而言都可以构造出这种情况,每个值都有与它相等的堆而且都是偶数个

但是由于必须要取走至少一个,所以只有一种情况下,不能满足就是已经是必败态了

所以你只需要判断是否是给定堆的时候就已经是必败态了,否则其余的状态都可以转换成必败态

//allblue All Rights Reserved

#include <stdio.h>
#include <string.h>
#define maxn 105

int main()
{
	int n;
	while(~scanf("%d",&n)&&n){
		int d[maxn];
		memset(d,0,sizeof(d));
		for (int i=0;i<n;i++){
			int data;scanf("%d",&data);
			d[data]++;
		}
		
		int flags=0;
		for (int i=1;i<=100;i++){
			if (d[i]&1){
				flags=1;
				break;
			}
		}
		
		printf("%d\n",flags);
		
	}
	return 0;
}

D.猜单词

暴力逐一扫瞄过去即可,每扫一次就要更新下原串,把扫过的值改成其余不可能存在的值即可,然后再记录使用次数即可

#include <bits/stdc++.h>
using namespace std;
int main()
{
	//freopen("F:\\TestFiles\\test.in","r",stdin);
	//freopen("F:\\TestFiles\\test2.out","w",stdout);
	char a[50],b[50];
	while(~scanf("%s%s",a,b)){
		int wr=0;
		int len1=strlen(a);
		int len2=strlen(b);
		
		
		int ans=0;
		for (int i=0;i<len2;i++){
			int flags=0;
			for (int j=0;j<len1;j++){
				if (a[j]==b[i]){
					flags=1;
					a[j]='*';
					ans++;
				}
			}
			
			if (!flags){
				wr++;
			}
			
		}
		
		if (wr<=6&&ans==len1){
			printf("You win.\n");
		}
		
		if (wr<=6&&ans<len1){
			printf("You chickened out.\n");
		}
		
		if (wr>6){
			printf("You lose.\n");
		}
		
	}
	return 0;
}


E.果园里的树

很裸的计算几何题目,直接枚举1w个点是否在三角行里面即可

用叉积计算面积

#include <bits/stdc++.h>
using namespace std;


#define PI acos(-1)
#define eps 1e-5
#define INF 1e16
typedef long long ll;

int sgn(double d) {
  return (d>+eps)-(d<-eps);
}

int fcmp(double a, double b) {
  return sgn(a-b);
}

struct Pnt{
	double x,y;
	Pnt(){};
	Pnt(double a,double b){
		x=a,y=b;
	}
	
	friend Pnt operator + (Pnt a,Pnt b){
		Pnt c;
		c.x=a.x+b.x;
		c.y=a.y+b.y;
		return c;
	}
	
	friend Pnt operator - (Pnt a,Pnt b){
		Pnt c;
		c.x=a.x-b.x;
		c.y=a.y-b.y;
		return c;
	}	
	
	friend double operator * (Pnt a,Pnt b){
		return a.x*b.x+a.y*b.y;
	}
	
	friend double operator ^ (Pnt a,Pnt b){
		return a.x*b.y-a.y*b.x;
	}
	
	friend bool operator == (Pnt a,Pnt b) {
		return fcmp(a.x, b.x)==0 && fcmp(a.y, b.y)==0;
	}
};

struct Seg{
	Pnt a;
	Seg(){};
	Seg(Pnt x,Pnt y){
		a=y-x;
	}
	
	friend Seg operator + (Seg a,Seg b){
		Seg c;
		c.a.x=a.a.x+b.a.x;
		c.a.y=a.a.y+b.a.y;
		return c;
	}
	
	friend Seg operator - (Seg a,Seg b){
		Seg c;
		c.a.x=a.a.x-b.a.x;
		c.a.y=a.a.y-b.a.y;
		return c;
	}	
	
	friend double operator * (Seg a,Seg b){
		return a.a.x*b.a.x+a.a.y*b.a.y;
	}
	
	friend double operator ^ (Seg a,Seg b){
		return a.a.x*b.a.y-a.a.y*b.a.x;
	}
	
	double length(){
		return sqrt(a.x*a.x+a.y*a.y);
	}
	
};


double ffabs(double data){
	if (data<0) return -data;
	return data;
}


int main()
{
	//freopen("F:\\TestFiles\\data.in","r",stdin);
	//freopen("F:\\TestFiles\\data2.out","w",stdout);
	Pnt a[4];
	int testcase=1;
	while(~scanf("%lf%lf",&a[0].x,&a[0].y)){
		scanf("%lf%lf%lf%lf",&a[1].x,&a[1].y,&a[2].x,&a[2].y);
		
		double mian=(0.5*ffabs((a[1]-a[0])^(a[2]-a[0])));
		
		int ans=0;
		
		for (double i=0;i<100;i++){
			for (double j=0;j<100;j++){
				Pnt c;
				c.x=i;c.y=j;
				
				double mian1=(0.5*ffabs((a[0]-c)^(a[1]-c)));
				double mian2=(0.5*ffabs((a[0]-c)^(a[2]-c)));
				double mian3=(0.5*ffabs((a[2]-c)^(a[1]-c)));
				if(sgn(mian-mian1-mian2-mian3)==0){
					ans++;
				}
			}
		}
		
		printf("Case #%d: %d\n",testcase++,ans);
		
	}
	return 0;
}

F.解密

模拟计算循环减2或者加2即可

只是需要注意a,b,y,z这四个字符的计算需要单独考虑

不能单纯的加减2即可

#include <bits/stdc++.h>
using namespace std;
int main()
{
	//freopen("F:\\TestFiles\\test.in","r",stdin);
	//freopen("F:\\TestFiles\\test2.out","w",stdout);
	char a[100005],b[100005];
	while(gets(a)!=NULL){
		int len=strlen(a);
		if (a[0]-'D'==0){
			for (int i=2;i<len;i++){
				if (!((a[i]<='z'&&a[i]>='a')||(a[i]<='Z'&&a[i]>='A'))){
					b[i-2]=a[i];
				}
				else
				{
					if (a[i]=='a') b[i-2]='y';
					else
					if (a[i]=='A') b[i-2]='Y';
					else
					if (a[i]=='b') b[i-2]='z';
					else
					if (a[i]=='B') b[i-2]='Z';
					else
					{
						b[i-2]=a[i]-2;
					}
				}
			}
		}
		else
		{
			for (int i=2;i<len;i++){
				if (!((a[i]<='z'&&a[i]>='a')||(a[i]<='Z'&&a[i]>='A'))){
					b[i-2]=a[i];
				}
				else
				{
					if (a[i]=='y') b[i-2]='a';
					else
					if (a[i]=='Y') b[i-2]='A';
					else
					if (a[i]=='z') b[i-2]='b';
					else
					if (a[i]=='Z') b[i-2]='B';
					else
					{
						b[i-2]=a[i]+2;
					}
				}
			}
		}
		
		for (int i=0;i<len-2;i++){
			printf("%c",b[i]);
		}
		printf("\n");
	}
	return 0;
}

G.数字金字塔

很裸的dp了

d[i][j],从i,j这点出发能走到的最大值

d[i][j]=max(d[i+1][j],d[i+1][j+1])+a[i][j]

#include<stdio.h>
#include<string.h>
long d[1001][1001];
long a[1001][1001];
long max(long as,long ad)
{
    if (as>ad)  return as;
    else return ad;
}
long dp(int i,int j)
{
    if (d[i][j]>-1) return d[i][j];
    d[i][j]=max(dp(i+1,j),dp(i+1,j+1))+a[i][j];
    return d[i][j];
}
int main()
{
    int r;
    while(scanf("%d",&r)==1)
    {
        memset(d,-1,sizeof(d));
        memset(a,0,sizeof(a));
        for (int i=1;i<=r;i++)
        {
            for (int j=1;j<=i;j++)
                scanf("%d",&a[i][j]);
        }
        for (int i=1;i<=r;i++)
            d[r][i]=a[r][i];
        printf("%ld\n",dp(1,1));
    }
    return 0;
}

H.局部极大值

暴力枚举,其实只要一个3*3的数组就可以存了

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m)){
		int a[25][25];
		for (int i=0;i<n;i++){
			for (int j=0;j<m;j++){
				scanf("%d",&a[i][j]);
			}
		}
		
		int flags=0;
		for (int i=1;i<n-1;i++){
			for (int j=1;j<m-1;j++){
				if (a[i][j]>a[i][j-1]&&a[i][j]>a[i][j+1]&&a[i][j]>a[i-1][j]&&a[i][j]>a[i+1][j]){
					printf("%d %d %d\n",a[i][j],i+1,j+1);
					flags=1;
				}
			}
		}
		
		if (!flags){
			printf("None %d %d\n",n,m);
		}
		
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值