# 2017上海金马五校程序设计竞赛部分题解

### Problem A : STEED Cards

(Out of Contest)

Time Limit: 1 s

## Description

Corn does not participate the STEED contest, but he is interested in the word "STEED". So, Corn writes all permutations of the word "STEED" on different cards and gets 60 cards finally.

Corn sorts these cards in lexicographical order, and marks them from 1 to 60.

Now, Corn gives you a integer N (1 ≤ N ≤ 60), could you tell him the word on the Nth card?

## Input

There are multiple test cases (no more than 60).
For each test case, there is one integer N (1 ≤ N ≤ 60) in a line.

## Output

For each test case, you should output one line with the word on the Nth card.

## Sample Input

1
2
3
4
47
48
49


## Sample Output

DEEST
DEETS
DESET
DESTE
STEDE
STEED
TDEES


Author: Corn

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
int i=-1,j;
char a[]={'D','E','E','S','T'};
string s[70];
do
{
i++;
for(j=0;j<5;j++)
s[i]+=a[j];
}while(next_permutation(a,a+5));
int n;
while(~scanf("%d",&n))
{
cout<<s[n-1]<<endl;
}
return 0;
}

### Problem B : Sailing

(Out of Contest)

Time Limit: 1 s

## Description

Handoku is sailing on a lake at the North Pole. The lake can be considered as a two-dimensional square plane containing N× N blocks, which is shown in the form of string containing '*' and '#' on the map.

• * : a normal block;
• # : a block containing pack ice.

Handoku is at (1, 1) initially, and his destination is (NN). He can only move to one of the four adjacent blocks. Sailing around pack ice is dangerous and stressful, so he needs power to remain vigilant. That means if he moves from a '*' block to a '#' block or moves from a '#' block to any another block, he needs to consume 1 unit power. In other cases, he can enjoy the scene on his boat without consuming any power.

Now Handoku wants to know how many units power will be consumed at least during his sailing on the lake.

## Input

There are several test cases (no more than 20).
For each test case, the first line contains a single integer N (3 ≤ N ≤ 50), denoting the size of the lake. For the following Nlines, each line contains a N-length string consisting of '*' and '#', denoting the map of the lake.

## Output

For each test case, output exactly one line containing an integer denoting the answer of the question above.

## Sample Input

3
**#
**#
*#*
3
##*
#*#
###
4
**##
#**#
##**
###*


## Sample Output

2
4
0


Author: handoku

*:代表一个正常的方格
#:代表一个包含冰块的方格
Handoku起初在（1,1）位置并且他的目标是(N,N),他只有四个方向可以移动,在包含冰块的方格附近移动是危险又有压力的所以他需要能量去保持机警,这意味着如果他从'*'到'#'或是从'#'到任意一个方格,都需要花费一单元的能量.在其他情况下不用花费任何能量.现在Handoku想知道他在这次航行中至少要花费多少？

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//四个方向
int n,a[52][52],vis[52][52];
struct node
{
int x,y;
int time;
friend bool operator<(node a,node b)//优先队列优先从小到大
{
return a.time>b.time;
}
}pre,now;
void bfs()
{
priority_queue<node>q;
pre.x=1;
pre.y=1;
pre.time=0;
q.push(pre);
while(!q.empty())
{
now=q.top();
q.pop();
if(now.x==n&&now.y==n)
{
printf("%d\n",now.time);
break;
}
for(int i=0;i<4;i++)
{
pre.x=now.x+dir[i][0];
pre.y=now.y+dir[i][1];
if(pre.x>=1&&pre.x<=n&&pre.y>=1&&pre.y<=n)
{
if(a[pre.x][pre.y]=='#'||a[now.x][now.y]=='#')
pre.time=now.time+1;//如果他从'*'到'#'或是从'#'到任意一个方格,都需要花费一单位的能量
else
pre.time=now.time;//在其他情况下不用花费任何能量
if(vis[pre.x][pre.y]>pre.time)
{//如果再次走过当前点比当前点保存的时间短就更新并入队，而不是说走过一个点就标记不能再走了
vis[pre.x][pre.y]=pre.time;
q.push(pre);
}
}
}
}
}
int main()
{
while(~scanf("%d",&n))
{
int i,j;
for(i=1;i<=n;i++)
{
getchar();//这个地方不要忘了加
for(j=1;j<=n;j++)
scanf("%c",&a[i][j]);
}
memset(vis,INF,sizeof(vis));//用来存放方格中到达当前点所消耗的最小能量
bfs();
}
return 0;
}


### Problem C : Count the Number

(Out of Contest)

Time Limit: 3 s

## Description

Given n numbers, your task is to insert '+' or '-' in front of each number to construct expressions. Note that the position of numbers can be also changed.

You can calculate a result for each expression. Please count the number of distinct results and output it.

## Input

There are several cases.
For each test case, the first line contains an integer n (1 ≤ n ≤ 20), and the second line contains n integers a1,a2, ... ,an(-1,000,000,000 ≤ ai ≤ 1,000,000,000).

## Output

For each test case, output one line with the number of distinct results.

## Sample Input

2
1 2
3
1 3 5


## Sample Output

4
8


Author: Sherry

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int aa[21],x[2000005];//x数组用于标记数字是否出现过
void f(int n)//将十进制转化为二进制数字
{
int i=0;
while(n!=0)
{
aa[i++]=n%2;
n/=2;
}
}
int main()
{
int n,a[25],k,b[21]={0},s[25]={0},l;
b[0]=1,s[0]=1;
for(k=1;k<20;k++)
{
b[k]=b[k-1]*2;//b数组存放2的次幂
s[k]=s[k-1]+b[k];//s数组存放前n项2的次幂之和
}
while(~scanf("%d",&n))
{
int i,j,c=0;
memset(x,0,sizeof(x));
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<=s[n-1];i++)
{
l=0;
memset(aa,0,sizeof(aa));//每次初始化
f(i);//得到当前数字的二进制，得到各种'+'或'-'插入的可能的结果
for(j=0;j<n;j++)
l+=aa[j]*a[j];
if(x[l]==0)
{
x[l]=1;
c++;//存放最后结果
}
}
printf("%d\n",c);
}
return 0;
}


### Problem E : Find Palindrome

(Out of Contest)

Time Limit: 1 s

## Description

Given a string S, which consists of lowercase characters, you need to find the longest palindromic sub-string.

A sub-string of a string S  is another string S'  that occurs "in" S. For example, "abst" is a sub-string of "abaabsta". A palindrome is a sequence of characters which reads the same backward as forward.

## Input

There are several test cases.
Each test case consists of one line with a single string S (1 ≤ || ≤ 50).

## Output

For each test case, output the length of the longest palindromic sub-string.

## Sample Input

sasadasa
bxabx
zhuyuan


## Sample Output

7
1
3


Author: Kenny

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
char a[100],b[100];
int dp[100][100];
while(gets(a))
{
int i,j,len,maxn=0;
len=strlen(a);
for(i=0;i<len;i++)
b[i]=a[len-1-i];//将a字符串反过来
memset(dp,0,sizeof(dp));
for(i=1;i<=len;i++)
for(j=1;j<=len;j++)
{
if(a[i-1]==b[j-1])
dp[i][j]=dp[i-1][j-1]+1;
if(dp[i][j]>maxn&&len-i==j-dp[i][j]&&len-(i-dp[i][j])-1==j-1)//注意这里的判断条件就是我所强调的
maxn=dp[i][j];
}
printf("%d\n",maxn);
}
return 0;
}

### Problem I : Frog's Jumping

(Out of Contest)

Time Limit: 1 s

## Description

There are n lotus leaves floating like a ring on the lake, which are numbered 0, 1, ..., n-1 respectively. The leaf 0 and n-1 are adjacent.

The frog king wants to play a jumping game. He stands at the leaf 0 initially. For each move, he jumps k (0 < k < n) steps forward. More specifically, if he is standing at the leaf x, the next position will be the leaf (x + k) % n.

After n jumps, he wants to go through all leaves on the lake and go back to the leaf 0 finally. He can not figure out how many different k can be chosen to finish the game, so he asks you for help.

## Input

There are several test cases (no more than 25).
For each test case, there is a single line containing an integer n (3 ≤ n ≤ 1,000,000), denoting the number of lotus leaves.

## Output

For each test case, output exactly one line containing an integer denoting the answer of the question above.

## Sample Input

4
5


## Sample Output

2
4


Author: handoku

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int a[1000005];
int main()
{
int n;
while(~scanf("%d",&n))
{
int i,j=0,m=n-1;//
memset(a,0,sizeof(a));
for(i=2;i<n;i++)
{
if(n%i==0)//满足是约数
{
for(j=1;j*i<n;j++)
if(a[j*i]==0)//约数的倍数
{
a[j*i]=1;//因为约数的倍数可能会有重复，所以用到标记数组
m--;
}
}
}
printf("%d\n",m);
}
return 0;
}


### Problem O : An Easy Problem

(Out of Contest)

Time Limit: 2 s

## Description

Zhu Ge is a very clever boy. One day, he discovered 2*n numbers. He wanted to divide them into n groups, each group contains 2 integers, and minimize the sum of the absolute value of the difference of the numbers in each group.

The problem is too difficult to Zhu Ge, so he turned to you. He hopes you can calculate the minimum of the sum of absolute value of the difference among different division strategies.

## Input

There are several test cases.
For each test case, there is an integer n (n < 10,000) at the first line. The second line contains 2*n integers. The input ends up with EOF.

## Output

For each test case, output the minimum of sum.

## Sample Input

3
10 3 4 5 1 6
5
64 5 63 63 23 63 54 64 3 54


## Sample Output

7
42


Author: Kuang

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
int n;
long long int a[30005];
while(~scanf("%d",&n))
{
int i;
for(i=0;i<2*n;i++)
scanf("%lld",&a[i]);
sort(a,a+2*n);
long long int s=0;
for(i=0;i<2*n;i+=2)
s+=a[i+1]-a[i];
printf("%lld\n",s);
}
return 0;
}