本周出现了博弈论,,嗯,这个方面我是空白的==
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;
}
其实这题初看不会做
后来网上查了下,这是楼教主男人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;
}