#include<stdio.h>
#include<math.h>

int main() {
	int a, b;
	while (scanf("%d %d", &a, &b)) {
		if (!(a + b))printf("1\n");
		printf("%d\n",(int)log10(a+b) + 1);
	}
	return 0;
}

Global OOD problem IDs are disjoint from train, validation, and in-distribution test problem IDs.

Digit Number

Write a program which computes the digit number of sum of two integers a and b.

Input

There are several test cases. Each test case consists of two non-negative integers a and b which are separeted by a space in a line. The input terminates with EOF.

Constraints

0 ≤ a, b ≤ 1,000,000

The number of datasets ≤ 200

Output

Print the number of digits of a + b for each data set.

Sample Input

5 7
1 99
1000 999

Output for the Sample Input

2
3
4

Submitted source-code file size, in bytes.

Execution CPU time reported by official Project CodeNet metadata, in milliseconds.

Peak memory usage reported by official Project CodeNet metadata, in kilobytes.


#include<stdio.h>
int check(int a,int b,int c){
	return (a*a==b*b+c*c||b*b==a*a+c*c||c*c==b*b+a*a)?1:0;
}
int main(){
	int x,y,a,b,c;
	scanf("%d",&x);
	int *ans;
	ans=(int*)malloc(sizeof(int)*x);
	for(y=0;y<x;x++){
		scanf("%d %d %d",&a,&b,&c);
		if(1==check(a,b,c))ans[y]=1;
		else ans[y]=0;
	}
	for(y=0;y<x;x++){
		if(y)printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

Is it a Right Triangle?

Write a program which judges wheather given length of three side form a right triangle. Print "YES" if the given sides (integers) form a right triangle, "NO" if not so.

Input

Input consists of several data sets. In the first line, the number of data set, N is given. Then, N lines follow, each line corresponds to a data set. A data set consists of three integers separated by a single space.

Constraints

1 ≤ length of the side ≤ 1,000

N ≤ 1,000

Output

For each data set, print "YES" or "NO".

Sample Input

3
4 3 5
4 3 6
8 8 8

Output for the Sample Input

YES
NO
NO


#include <stdio.h>

int main(void) {
	long a,b;
	while(EOF!=scanf("%d %d",&a,&b)){
		long i,j;
		long mini=a,big=b;
		if(a>b){
		    mini=b;
		    big=a;
		}
		for(i=mini;a%i!=0 || b%i!=0;i--);
		for(j=big;j%a!=0 || j%b!=0;j=j+big);
		printf("%d %d\n",i,j);
	}
	return 0;
}

GCD and LCM

Write a program which computes the greatest common divisor (GCD) and the least common multiple (LCM) of given a and b.

Input

Input consists of several data sets. Each data set contains a and b separated by a single space in a line. The input terminates with EOF.

Constraints

0 < a, b ≤ 2,000,000,000

LCM(a, b) ≤ 2,000,000,000

The number of data sets ≤ 50

Output

For each data set, print GCD and LCM separated by a single space in a line.

Sample Input

8 6
50000000 30000000

Output for the Sample Input

2 24
10000000 150000000


Sum of 4 Integers

Write a program which reads an integer n and identifies the number of combinations of a, b, c and d (0 ≤ a, b, c, d ≤ 9) which meet the following equality:

a + b + c + d = n

For example, for n = 35, we have 4 different combinations of (a, b, c, d): (8, 9, 9, 9), (9, 8, 9, 9), (9, 9, 8, 9), and (9, 9, 9, 8).

Input

The input consists of several datasets. Each dataset consists of n (1 ≤ n ≤ 50) in a line. The number of datasets is less than or equal to 50.

Output

Print the number of combination in a line.

Sample Input

35
1

Output for the Sample Input

4
4


#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int is_prime(int);

int main()
{
	int input_count;
	int prime_count;
	int input;
	int for_cnt;
	int output[30];

	input_count = 0;

	while(scanf("%d", &input) != EOF && input_count < 30)
	{
		prime_count = 0;

		if(input >= 2)
		{
			prime_count++;
		}
		for_cnt = 3;
		while(for_cnt <= input)
		{
			if(is_prime(for_cnt))
			{
				prime_count++;
			}
			for_cnt += 2;
		}
		output[input_count] = prime_count;
		input_count++;
	}

	for(for_cnt = 0; for_cnt < input_count; for_cnt++)
	{
		printf("%d\n", output[for_cnt]);
	}

    return 0;
}

int is_prime(int test_num)
{
	int divisor;

	if(test_num == 1)
	{
		return 0;
	}
	else if(test_num == 2 || test_num == 3 || test_num == 5 || test_num == 7)
	{
		return 1;
	}
	else if((test_num % 2) == 0)
	{
		return 0;
	}

	for(divisor = 3 ; divisor <= (sqrt(test_num) + 1); divisor += 2)
	{
		if(test_num % divisor == 0)
		{
			return 0;
		}
	}

	return 1;
}

Prime Number

Write a program which reads an integer n and prints the number of prime numbers which are less than or equal to n. A prime number is a natural number which has exactly two distinct natural number divisors: 1 and itself. For example, the first four prime numbers are: 2, 3, 5 and 7.

Input

Input consists of several datasets. Each dataset has an integer n (1 ≤ n ≤ 999,999) in a line.

The number of datasets is less than or equal to 30.

Output

For each dataset, prints the number of prime numbers.

Sample Input

10
3
11

Output for the Sample Input

4
2
5


#include<stdio.h>
int main()
{
	int s,i,j;
	int bbb,ccc;
	while((scanf("%d",&s))!=EOF)
	{
		bbb=0;
		for(i=2;i<=s;i++)
		{
			ccc=0;
			for(j=1;j<=i;j++)
			{
				if(i%j==0)
				{
					ccc++;
				}
			}
			if(ccc==2)
			{
				bbb++;
			}
		}
		printf("%d\n",bbb);
	}
	return 0;
}


//#include "stdafx.h"
#include <stdio.h>
#include <math.h>

int main()
{
    int n,i,p=0,j,judge=0,a[200000];
	while(scanf("%d",&n)!=EOF)
	{
		if (n==1)
			p=0;
		else{
			p=1;//i=2,p++
			a[1]=2;
		for (i=2;i<=n;i++)
		{
			judge=0;
			for (j=1;j<=p;j++)
			{
				if (i%a[j]==0){
					judge=1;
					break;}
				if (j>=4){
				if (7*a[j]>i)
					break;}
			}
			if (judge==0){
				p++;
				a[p]=i;
			}
		}
		}
		printf("%d\n",p);
	}
	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#define FALSE 0
#define TRUE 1

int main (int argc, char* argv[])
{
  int i, p, k, count, n;
  char flag[1000000];

  while (scanf("%d", &n) != EOF) {
    count = 1;
    for (i=0; i<=n; i++) {
      flag[i] = TRUE;
    }
    for (i=0; i<=n; i++) {
      if (flag[i]) {
	p = i + i + 3;
	for (k=i+p; k<=n; k+=p) {
	  flag[k] = FALSE;
	}
	if (p <= n) {
	  count++;
	}
      }
    }
    printf("%d\n", count);
  }

  return 0;
}


#include <stdio.h>
#include <math.h>

int main()
{
  int setcount;
  float x1, y1, x2, y2, x3, y3;
  float nx1, ny1, nx2, ny2;
  float nr1, nr2;
  float xp, yp, r;
  int tx, ty, tr, rem;
  int i;

  scanf("%d", &setcount);
  for(i=0; i<setcount; i++){
    scanf("%f %f %f %f %f %f", &x1, &y1, &x2, &y2, &x3, &y3);
    nx1=x2-x1; ny1=y2-y1;
    nx2=x3-x1; ny2=y3-y1;
    nr1=nx1^2+ny1^2; nr2=nx2^2+ny2^2;
    nr1*=0.5f; nr2*=0.5f;

    xp=nr1+x1; yp=nr2+y1;
    r=(float)sqrt((double)(nr1^2+nr2^2));
    tx=xp*10000; ty=yp*10000; tr=r*10000;
    if((rem=tx%10)<5) tx-=rem;
    else tx+=10-rem;
    if((rem=ty%10)<5) ty-=rem;
    else ty+=10-rem;
    if((rem=tr%10)<5) tr-=rem;
    else tr+=10-rem;
    xp=(float)tx*0.0001f; yp=(float)ty*0.0001f; r=(float)tr*0.0001f;

    printf("%.3f %.3f %.3f\n", xp, yp, r);
  }

  return 0;
}

MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Circumscribed Circle of A Triangle.

Write a program which prints the central coordinate $(p_x, p_y)$ and the radius $r$ of a circumscribed circle of a triangle which is constructed by three points $(x_1, y_1)$, $(x_2, y_2)$ and $(x_3, y_3)$ on the plane surface.

Input

Input consists of several datasets. In the first line, the number of datasets $n$ is given. Each dataset consists of:

$x_1$ $y_1$ $x_2$ $y_2$ $x_3$ $y_3$

in a line. All the input are real numbers.

Output

For each dataset, print $p_x$, $p_y$ and $r$ separated by a space in a line. Print the solution to three places of decimals. Round off the solution to three decimal places.

Constraints

$-100 \leq x_1, y_1, x_2, y_2, x_3, y_3 \leq 100$

$ n \leq 20$

Sample Input

1
0.0 0.0 2.0 0.0 2.0 2.0

Output for the Sample Input

1.000 1.000 1.414


#include<stdio.h>
main(){long long n,i;scanf("%d",&n);for(i=n;--n;)i*=n;printf("%d\n",i);}

Factorial

Write a program which reads an integer n and prints the factorial of n. You can assume that n ≤ 20.

Input

An integer n (1 ≤ n ≤ 20) in a line.

Output

Print the factorial of n in a line.

Sample Input

5

Output for the Sample Input

120


#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main(void)
{
  int n,*a,i,j,k,tmp,max;
  while(1){
    scanf("%d",&n);
    if(n==0)
      break;
    a=malloc(sizeof(int)*n);
    for(i=0;i<n;i++)
      scanf("%d",&a[i]);

    //for(i=0;i<n;i++)
    // printf("%d\n",a[i]);

    max=-9999;
    tmp=0;
    for(i=0;i<n;i++){
      for(j=1;j<=n-i;j++){
	for(k=i;k<i+j;k++)
	  tmp+=a[k];
	//printf("tmp=%d\n",tmp);
	if(tmp>max)
	  max=tmp;
	tmp=0;
      }
    }
    printf("%d\n",max);
  }

  return 0;
}

Maximum Sum Sequence

Given a sequence of numbers a1, a2, a3, ..., an, find the maximum sum of a contiguous subsequence of those numbers. Note that, a subsequence of one element is also a contiquous subsequence.

Input

The input consists of multiple datasets. Each data set consists of:

n
a1
a2
.
.
an

You can assume that 1 ≤ n ≤ 5000 and -100000 ≤ ai ≤ 100000.

The input end with a line consisting of a single 0.

Output

For each dataset, print the maximum sum in a line.

Sample Input

7
-5
-1
6
4
9
-6
-7
13
1
2
3
2
-2
-1
1
2
3
2
1
-2
1
3
1000
-200
201
0

Output for the Sample Input

19
14
1001


#include <stdio.h>

int main() {
	int prime[10000];
	int i,j,k,n;
	prime[0]=prime[1]=2;

	for(i=2;j<10000;i++){
		for(k=0;k<j;k++){
			if(i%prime[k]==0)break;
		}
		if(k>=j){
			prime[j]=i;
			j++;
		}
	}

	for(i=1;i<10000;i++){
		prime[i]+=prime[i-1];
	}

	while(1){
		scanf("%d", &n);
		if(n==0) break;
		printf("%d\n", prime[n-1]);
	}
	return 0;
}

素数の和

p(i) を小さい方から i 番目の素数とします。例えば、7 は、2, 3, 5, 7 と小さい方から 4 番目の素数なので、p(4) = 7 です。

n が与えられたとき、i = 1 から n までの p(i) の和 s

s = p(1) + p(2) + .... + p(n)

を出力するプログラムを作成してください。例えば、n = 9 のとき、s = 2 + 3 + 5 + 7 + 11 + 13 + 17 + 19 + 23 = 100 となります。

Input

複数のデータセットが与えられます。各データセットに整数 n (n ≤ 10000) が与えられます。n が 0 のとき入力の最後とします。データセットの数は 50 を超えません。

Output

各データセットの n に対して、s を１行に出力して下さい。

Sample Input

2
9
0

Output for the Sample Input

5
100


// AOJ Volume 0 Problem 0070

#include <stdio.h>
#include <string.h>

int no;
int n, s;

void combination(int num[], int depth, int sum)
{
	int i;

	if (depth == 1){
			if (num[s - sum] == 0){
				no++;
			}
		return;
	}

	if (s < sum){
		return;
	}

	for (i = 0; i <= 9; i++){
		if (num[i] == 0){
	if (sum + i * depth > s){
		return;
	}
			num[i] = 1;
			combination(num, depth - 1, sum + i * depth);
			num[i] = 0;

		}
	}
}

int main(void)
{
	int num[10];

	while (scanf("%d%d", &n, &s) != EOF){
		no = 0;
		memset(num, 0, sizeof(num));
		combination(num, n, 0);

		printf("%d\n", no);
	}

	return (0);
}

Combination of Number Sequences

0 から 9 までの整数を使った n 個の数の並び k1, k2, ..., kn を考えます。正の整数 n と s を読み込んで、

k1 + 2 × k2 + 3 × k3 + ... + n × kn = s

となっているような n 個の数の並びが何通りあるかを出力するプログラムを作成してください。ただし、1 つの「n 個の数の並び」には同じ数が 2 回以上現われないものとします。

Input

入力は複数のデータセットからなります。各データセットとして、n (1 ≤ n ≤ 10) と s (0 ≤ s ≤ 10,000)が空白区切りで１行に与えられます。

データセットの数は 100 を超えません。

Output

データセットごとに、n 個の整数の和が s になる組み合わせの個数を１行に出力します。

Sample Input

3 10
3 1

Output for the Sample Input

8
0


// AOJ Volume 0 Problem 0070

#include <stdio.h>
#include <string.h>

int no;
int n, s;
int num[10];

void combination_even(int depth, int sum)
{
	int i;

	if (s < sum){
		return;
	}

	if (depth == 2){
		if ((s - sum) % 2 == 0 && (s - sum) / 2 <=9  && num[(s - sum) / 2] == 0){
			no++;
		}
		return;
	}

	for (i = 9; i >= 0; i--){
		if (num[i] == 0){
            if (sum + i * depth <= s){
            	num[i] = 1;
			    combination_even(depth - 2, sum + i * depth);
			    num[i] = 0;
            }
		}
	}
}

void combination(int depth, int sum)
{
	int i;

	if (s < sum){
		return;
	}

	if (depth == -1){
		if ((sum % 2) == (s % 2)){
			combination_even(n / 2 * 2, sum);
		}
		return;
	}

	for (i = 9; i >= 0; i--){
		if (num[i] == 0){
            if (sum + i * depth <= s){
            	num[i] = 1;
			    combination(depth - 2, sum + i * depth);
			    num[i] = 0;
            }
		}
	}
}

int main(void)
{

	while (scanf("%d%d", &n, &s) != EOF){
		no = 0;
		memset(num, 0, sizeof(num));
		combination((n + 1) / 2 * 2 + 1, 0);

		printf("%d\n", no);
	}

	return (0);
}


シールの重なり

1 辺の長さが 10 の正方形の折り紙に半径 1 の円形のシールを n 枚貼ります。シールは重ねて貼ることができます。シールを貼る位置の座標を読み込んで、折り紙上でもっとも多くシールが重なっている場所(シールが１枚だけでも"重なっている"とする)でのシールの枚数を出力するプログラムを作成してください。

折り紙の左下を原点とした x, y 座標を与えます。この x, y を円の中心としてシールを貼ることとします。円の中心が折り紙の外に出ることはありません。また、同一座標に複数のシールが貼られることはありません。

Input

複数のデータセットが与えられます。各データセットは以下のような形式で与えられます。

n
x1,y1
x2,y2
:
xn,yn

１行目にシールの枚数 n (0 ≤ 100) が与えられます。続く n 行に、各シールの中心座標が与えられます。
xi, yi は i 枚目のシールの中心の x 座標と y 座標を表します。各値は小数点以下最大 6 桁までの数字を含む実数で与えられます。

n が 0 のとき、入力の最後とします。データセットの数は 50 を超えません。

Output

各データセットに対し、折り紙上で最も多くシールが重なっている場所でのシールの枚数（整数）を出力して下さい。

Sample Input

15
3.14979,8.51743
2.39506,3.84915
2.68432,5.39095
5.61904,9.16332
7.85653,4.75593
2.84021,5.41511
1.79500,8.59211
7.55389,8.17604
4.70665,4.66125
1.63470,4.42538
7.34959,4.61981
5.09003,8.11122
5.24373,1.30066
0.13517,1.83659
7.57313,1.58150
0

Output for the Sample Input

4

Hint

入力例のようにシールを貼った図です。円はシール、数字は入力例の行数を表しています。
点(2.3,4.6)では、入力例の 2 行目、3 行目、6 行目、10 行目の 4 枚のシールが重なっています。

6 と 9 のおのおのの中心の距離は 2.01293 なので、シールは重なっていません。1 と 12 のおのおのの中心の距離は 1.98231 なので、シールは重なっています。

２つの円が接しているとき（おのおのの中心の距離が 2 のとき）は、重なっているものとします。


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
	int *A;
	const char H[4] = "HIT";
	const char R[8] = "HOMERUN";
	const char O[4] = "OUT";
	while(1){
		int score = 0;
		int runner = 0;
		int out = 0;
		char s[10];
		scanf("%s",s);
		if(strcmp(s,H) == 0)
		{
			runner++;
			if(runner == 4)
			{
				score++;
				runner--;
			}
		}
		else if(strcmp(s,R) == 0)
		{
			score = score + runner + 1;
			runner = 0;
		}
		else if(strcmp(s,O) == 0) out++;
		if(out == 3) printf("%d ",score);
	}
	return 0;
}

Baseball Simulation

Ichiro likes baseball and has decided to write a program which simulates baseball.

The program reads events in an inning and prints score in that inning. There are only three events as follows:

Single hit

put a runner on the first base.

the runner in the first base advances to the second base and the runner in the second base advances to the third base.

the runner in the third base advances to the home base (and go out of base) and a point is added to the score.

Home run

all the runners on base advance to the home base.

points are added to the score by an amount equal to the number of the runners plus one.

Out

The number of outs is increased by 1.

The runners and the score remain stationary.

The inning ends with three-out.

Ichiro decided to represent these events using "HIT", "HOMERUN" and "OUT", respectively.

Write a program which reads events in an inning and prints score in that inning. You can assume that the number of events is less than or equal to 100.

Input

The input consists of several datasets. In the first line, the number of datasets n is given. Each dataset consists of a list of events (strings) in an inning.

Output

For each dataset, prints the score in the corresponding inning.

Sample Input

2
HIT
OUT
HOMERUN
HIT
HIT
HOMERUN
HIT
OUT
HIT
HIT
HIT
HIT
OUT
HIT
HIT
OUT
HIT
OUT
OUT

Output for the Sample Input

7
0


ブラックジャック

ブラックジャックはカジノで行われるカードゲームの一種で、1 〜 13 までの数が書かれたカードを使ってゲームが行われます。各カードの点数は次のように決まっています。

1 は 1 点あるいは 11 点

2 から 9 までは、書かれている数の通りの点数

10 から 13 までは、10 点

このゲームには親を含めた何人かの参加者がおり、それぞれが何枚かのカードの組を持っています。このカードの組のことを手と呼びます。手の点数はカードの点数の合計です。その計算は次のように行うものとします。

カードの点数の合計が 21 より大きくなるときは、手の点数を 0 点とする

カードの点数として、1 は 1 点と計算しても 11 点と計算してもよいが、手の点数が最大となる方を選ぶこととする

配られたカードの情報を入力とし、手の点数を出力するプログラムを作成してください。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロひとつの行で示されます。
各データセットは以下の形式で与えられます。

c1 c2 ... cn

１行に i 番目のカードに書かれている整数 ci (1 ≤ ci ≤ 13) が空白区切りで１行に与えられます。カードの数 n は 100 を超えません。

データセットの数は 200 を超えません。

Output

データセットごとに手の点数を１行に出力します。

Sample Input

1
7 7 7
7 7 8
12 1
10 1 1
0

Output for the Sample Input

11
21
0
21
12


#include <stdio.h>

int main(void)
{
	int a[100];
	int n;
	int i;
	int search_no;
	int index_min;
	int index;
	int index_max;
	int count;

	while (1){
		scanf("%d", &n);
		if (n == 0){
			break;
		}
		for (i = 0; i < n; i++){
			scanf("%d", &a[i]);
		}
		scanf("%d", &search_no);

		index_min = 0;
		index_max = n - 1;
		index = (index_min + index_max) / 2;

		count = 0;
		while(1){
			count++;

			if (a[index] == search_no || index_min >= index_max){
				break;
			}

			if (a[index] < search_no){
				index_min = index;
			}
			else {
				index_max = index - 1;
			}

			index = (index_min + index_max) / 2;
		}

		printf("%d\n", count);
	}

	return (0);
}

探索

「探索」とは、たくさんの情報の中から望みの情報を得る操作のことです。身近な例では、合格発表の時の「たくさんの受験番号から自分の受験番号を見つける」ことや、電話帳から「会津太郎さんの電話番号を見つける」ときなどがあります。この探索という操作はコンピュータの分野でも広く用いられています。

探索の方法は沢山あります。探索の対象となるデータが、小さい順(または大きい順)に並べられている場合に使うことができる探索の方法を考えます。

小さい順(または大きい順)に並べられているデータ列の中央に位置する値と目的の値との大小関係を用いて、中央に位置する値から前半部分を探索範囲にするか後半部分を探索範囲にするかを決めることで、探索の範囲を絞っていく方法があります。手順は以下のようになります。

データの列の全体を探索の範囲とします。

探索の範囲の中央に位置する値を調べます。

目的の値と中央に位置する値が一致すれば探索を終了します。

目的の値と中央に位置する値よりも小さければ前半部分を探索の範囲とし、大きければ後半部分を探索の範囲として2.へ戻ります。

以下は上述した探索の方法の例です。この例での目的の値は51です。それぞれのデータには番号
(index)が振られており、この番号は0から始まっています。

ステップ1: 最初は番号0~6全体を探索の範囲とします。

ステップ2: 探索の範囲の中央に位置する値を調べます。ただし、「中央に位置する値」とは、(左側の番号+右側の番号)を2で割った番号の位置にある値とします。つまり、この場合、(0 + 6) ÷ 2 を計算し、番号3にある値(36)が中央に位置する値となります。

ステップ3:目的の値(51)と中央に位置する値(36)を比較します。

ステップ4:ステップ3の結果から、目的の値は中央に位置する値より大きいので、後半部分にあたる番号4 (中央に位置する値の隣)以降を探索の範囲とします。同様の手順で探索の範囲の中央に位置する値を調べ、目的の値が中央に位置する値より小さければ前半部分を探索の範囲とし、大きければ後半部分を探索の範囲として、探索の範囲を小さくしていきます。(ステップ2~ステップ4の繰り返し)目的の値が中央に位置する値と一致するか、探索の範囲がつきてしまった時に探索を終了します。

n 個の数値の配列を入力とし、目的の値と中央に位置する値を比較した回数を出力するプログラムを作成してください。ただし、中央に位置する値の番号を計算したとき、割り切れない場合は、小数点以下を切り捨てた値をその番号とすることとします。
与えられるデータ列は小さい順に整列されているものとします。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロひとつの行で示されます。 各データセットは以下の形式で与えられます。

n
a1
a2
:
an
k

1 行目に数値の数 n (1 ≤ n ≤ 100) 、続く n 行に i 個目の数値 ai (1 ≤ ai ≤ 100000, 整数) が与えられます。

続く行に探索する値 k (1 ≤ k ≤ 100000) が与えられます。

Output

データセット毎に探索が終わるまでの比較回数を１行に出力します。

Sample Input

7
11
15
23
36
51
61
86
51
4
1
2
3
5
4
0

Output for the Sample Input

3
3


#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int search(int map[1000][1000],int n,int y,int x,int *hy,int *hx){
	int min = 1999, i, j, sy, sx,flag = 0;
	for(i = 0;i < y;i++){
		for(j = 0;j < x;j++){
			if(map[i][j] == n)
				flag = 1;
		}
	}
	if(flag == 1){
		for(i = 0;i < y;i++){
			for(j = 0;j < x;j++){
				if(map[i][j] == n && abs(*hy - i) + abs(*hx - j) < min){
					sy = i - *hy;
					sx = j - *hx;
					min = abs(sy) + abs(sx);
				}
			}
		}
		*hy = *hy + sy; *hx = *hx + sx;
		return min;
	}
	return 1999;
}
int main(void){
	int i, j, map[1000][1000], y, x, by, bx, gy, gx;
	int *hy, *hx, flag[5],wc[5],min_w,min_i,count,walk;
	char c;
	char str[5];
	hy = (int *)malloc(sizeof(int));
	hx = (int *)malloc(sizeof(int));
	scanf("%d%d",&x,&y);
	while(x != 0 || y != 0){
		for(i = 0;i < y;i++){
			for(j = 0;j < x;j++)
				map[i][j] = -1;
		}
		for(i = 0;i < y;i++){
			for(j = 0;j < x;j++){
				c = '\n';
				while((c = getchar()) == '\n');
				switch(c){
					case '.':
						map[i][j] = 0;
						break;
					case 'S':
						map[i][j] = 6;
						by = i;
						bx = j;
						break;
					case 'G':
						map[i][j] = 7;
						gy = i;
						gx = j;
						break;
					default:
						map[i][j] = atoi(&c);
				}
			}
		}
		for(i = 0;i < 5;i++)
			flag[i] = 0;
		count = 0;
		for(i = 0;i < y;i++){
			for(j = 0;j < x;j++){
				if(1 <= map[i][j] && map[i][j] <= 5 && flag[map[i][j] - 1] == 0){
					count++;
					flag[map[i][j] - 1] = 1;
					if(count > 3)
						break;
				}
			}
			if(count > 3)
				break;
		}
		if(count > 3){
			for(i = 0;i < 5;i++)
				wc[i] = 0;
			for(i = 0;i < 5;i++){
				*hy = by; *hx = bx; walk = 0;
				for(j = (i + 1) % 5;i != j;j = (j + 1) % 5)
					walk += search(map,j + 1,y,x,hy,hx);
				wc[i] = walk + abs(*hy - gy) + abs(*hx - gx);
			}
			min_w = wc[0];
			min_i = 1;
			for(i = 1;i < 5;i++){
				if(min_w > wc[i]){
					min_w = wc[i];
					min_i = i + 1;
				}
			}
			printf("%d %d\n",min_i,min_w);
		}
		else if(x == 0 || y == 0);
		else
			printf("NA\n");
		for(i = 0;i < 4;i++)
			str[i] = 0;
		while((str[0] = getchar()) == '\n' || str[0] == EOF || str[0] == ' ');
		for(i = 1;i < 4 && (c = getchar()) != ' ';i++)
			str[i] = c;
		x = atoi(str);
		scanf("%d",&y);
	}
	return 0;
}

パチモンクリーチャー

某国で大人気のゲーム、パチモンクリーチャーが日本でリメイクされて発売されました。 ゲームが大好きなあなたは、 このゲームを何度もプレイするうちにどうしたら最速でクリアできるのか考えるようになりました。しかし、いくら考えても最速の攻略方法がわからなかったあなたは、どれだけ早くゲームをクリアできるかを求めるプログラムを作成することにしました。

ゲームの詳細は以下の通りです。

パチモンクリーチャー(以下、パチクリ)という生物が多く存在する世界がゲームの舞台です。各パチクリは、火属性、氷属性、木属性、土属性、水属性の 5 種類の属性のいずれか１つの属性を持ちます。ゲームの主人公は、ゲーム開始時に好きな属性のパチクリ一匹を冒険のパートナーとして選びます。そのパチクリと共にゴールを目指し、ゴールにいるライバルを倒してパチクリマスターになることがゲームの目的です。

しかし、ライバルを倒すためには全属性のパチクリがいないと勝てないので、途中で全属性のパチクリを捕まえなければなりません。パチクリを捕まえるには属性がカギとなります。火属性のパチクリは氷属性のパチクリを捕まえることができ、同様に、氷属性は木属性、木属性は土属性、土属性は水属性、水属性は火属性を捕まえることができます。属性の関連は以下の図のようになります。

以下の図はゲームが行われるマップの一例を表しています。

主人公はパチクリを一匹もってスタート地点である「S」から出発し、一マスずつ移動しながらゴール地点である「G」を目指します。その途中で、最初に持っているパチクリ以外の 4 つの属性のパチクリを捕まえ、ゴール地点であるマス目に移動するとゲーム終了となります。

主人公は、今いるマス目から、辺を共有する隣のマス目に移動することができ、それを一回の移動と数えます。主人公がパチクリのいるマスに移動した場合、そのパチクリを捕まえられる属性のパチクリを持っていればそのパチクリを捕まえたことになります。そのマスにいるパチクリを捕まえられるかの可否にかかわらず、すべてのマスに何度でも移動することができます。

マップの大きさ(横方向の列数、縦方向の行数)とマップの初期状態を入力とし、初めに選んだパチクリの属性と、それ以外の 4 つの属性のパチクリを捕まえるのにかかる、スタート地点からゴール地点に至る最小移動数を出力するプログラムを作成してください。

Input

複数のデータセットの並びが入力として与えられます。入力の終りはゼロふたつの行で示されます。各データセットは以下の形式で与えられます。

W H
c11c12...c1W
c21c22...c2W
:
cH1cH2...cHW

1 行目にマップの横方向の列数 W と縦方向の行数 H (2 ≤ W, H ≤ 1000) が与えられます。続く H 行にマップの i 行目の情報が与えられます。入力されるマップには各マスの状態が与えられます。 「S」は主人公のスタート地点を、 「G」はゴール地点を、「1」「2」「3」「4」「5」はそこにいるパチクリの属性を( 1:火属性、 2:氷属性、 3:木属性、 4:土属性、 5:水属性 をそれぞれ表します)、 「.(ピリオド) 」は何もないマスをそれぞれ表します。
各属性のパチクリの数はそれぞれ 0 以上 1000 以下とします。

データセットの数は140 を超えません。また、データセットの 80 % について、W, H は100 を超えません。

Output

入力データセットごとに、最初に選んだパチクリの属性と最小移動数を１行に出力します。なお、どのように初めのパチクリを選んでも、どのような経路で移動してもそれら 4 つの属性のパチクリを捕まえることができない場合は NA と出力してください。 また、最小移動数が同じになるような最初のパチクリの選び方が複数ある場合は、属性の数字が小さいものを出力してください。

Sample Input

6 6
S.1..4
3..5..
..4.1.
4....5
.2.32.
5.1..G
3 2
...
S.G
0 0

Output for the Sample Input

2 10
NA


巨樹の刻み手

あなたは N 種類の道具を使って、目の前の巨樹を切り倒そうとしています。はじめは、樹の耐久力は D、あなたの経験値は 0 ですが、道具 i で１回樹を叩くと樹の耐久力は ai 減り、あなたは ei の経験値を得ます。ただし、道具 i を使うためには、あなたは ri 以上の経験値を持っていなければなりません。樹の耐久力が 0 以下になると樹は倒れます。

樹の耐久力と道具についての情報が与えられたとき、樹を切り倒すには最低何回樹を叩かなければいけないかを求めるプログラムを作成してください。

入力

入力は複数のデータセットからなる。入力の終わりはゼロ２つの行で示される。各データセットは以下の形式で与えられる。

D N
a1 e1 r1
a2 e2 r2
:
aN eN rN

1 行目に樹の耐久力を表す整数 D (1 ≤ D ≤ 100) と道具の種類の数 N(1 ≤ N ≤ 100) が与えられる。続く N 行に道具 1 から N までの情報が与えられる。ai (0 ≤ ai ≤ 100) と ei (0 ≤ ei ≤ 100) は、道具iを１回使うことで減る樹の耐久力とあなたが得ることのできる経験値をそれぞれ表す。ri (0 ≤ ri ≤ 100) は道具を使うために必要な経験値を表す。ai, ei, ri はすべて整数である。

データセットの数は 50 を超えない。

出力

樹を切り倒すのに必要な、樹を叩く最小の回数を１行に出力する。ただし、樹を切り倒すことが不可能な場合は NA と出力する。

入出力例

入力例

15 4
1 1 0
1 2 2
5 10 5
8 1 15
60 4
5 2 0
8 8 2
3 5 0
49 0 18
100 1
1 1 1
0 0

出力例

6
4
NA


#include <stdio.h>

int main()
{
	int n, m, i;
	char change[1000][2], c;

	while (1) {
		scanf("%d", &n);
		if (n == 0) break;
		for (i = 0;i < n;i++) {
			scanf("%c %c", &change[i][0], &change[i][1]);
		}
		scanf("%d", &m);
		while (m--) {
			scanf("%c", &c);

			for (i = 0;i < n;i++) {
				if (c == change[i][0]) {
					c = change[i][1];
					break;
				}
			}
			printf("%c", c);
		}
		printf("\n");
	}

	return 0;
}

与えられた変換表にもとづき，データを変換するプログラムを作成しなさい．

データに使われている文字は英字か数字で，英字は大文字と小文字を区別する．変換表に現れる文字の順序に規則性はない．

変換表は空白をはさんで前と後ろの 2 つの文字がある(文字列ではない)．変換方法は，変換表のある行の前の文字がデータに現れたら，そのたびにその文字を後ろの文字に変換し出力する．変換は 1 度だけで，変換した文字がまた変換対象の文字になっても変換しない．変換表に現れない文字は変換せず，そのまま出力する．

入力ファイルには，変換表（最初の n + 1 行）に続き変換するデータ（n + 2 行目以降）が書いてある． 1 行目に変換表の行数 n，続く n 行の各行は，空白をはさんで 2 つの文字，さらに続けて， n + 2 行目に変換するデータの行数 m，続く m 行の各行は 1 文字である． m ≤ 105 とする．出力は，出力例のように途中に空白や改行は入れず 1 行とせよ．

入力例

3

A a

0 5

5 4

10

A

B

C

0

1

4

5

a

b

A

出力例

aBC5144aba

入力

入力は複数のデータセットからなる．n が 0 のとき入力が終了する．データセットの数は 5 を超えない．

出力

データセットごとに、変換後の文字列を１行に出力する．

入力例

3
A a
0 5
5 4
10
A
B
C
0
1
4
5
a
b
A
3
A a
0 5
5 4
10
A
B
C
0
1
4
5
a
b
A
0

出力例

aBC5144aba
aBC5144aba

各データセットの出力（変換後の文字列）の後に改行を入れること．

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


#include<stdio.h>

void swap(int *a,int *b){
	int h;
	h=*a;
	*a=*b;
	*b=h;
}

int main(){
	int n,m,i,place[100],c,j,sort[100],p;
	scanf("%d %d",&n,&m);
	while(n!=0){
		for(j=0;j<m;j++){
			place[j]=0;
			sort[j]=-1;
		}
		for(i=0;i<n;i++){
			for(j=0;j<m;j++){
				scanf("%d",&c);
				place[j]+=c;
				if(sort[j]==-1) sort[j]=j;
				for(c=0;c<m;c++){
					if(sort[c]==j){
						p=j;
						c=m;
					}
				}
				for(c=p;c>0;c--){
					if(place[sort[c]]>place[sort[c-1]]){
						swap(&sort[c],&sort[c-1]);
					}else{
						c=0;
					}
				}
			}
		}
		for(i=1;i<m;i++){
			if(place[sort[i]]==place[sort[i-1]]){
				if(sort[i]<sort[i-1]){
				swap(&sort[i],&sort[i-1]);
				i=0;
				}
			}
		}
		printf("%d",sort[0]+1);
		for(i=1;i<m;i++){
			printf(" %d",sort[i]+1);
		}
		printf("\n");
		scanf("%d %d",&n,&m);
	}
	return 0;
}

ある学校で修学旅行へ行く計画がある.そのためにアンケート調査を行った.
生徒は 1 から n までの生徒番号を持ち,旅行候補の場所を 1 から m までの番号で表し,行きたい場所に ○,行きたくない場所に×の印をつけて提出している.

このとき, 行きたい場所の人数が多い順に,場所の番号を出力するプログラムを作成せよ.人数が同じときは,場所の番号順とする.

入力データ の 1 行目は生徒の人数 n と旅行候補の場所の数 m が空白で区切られ, i + 1 行に生徒 i のアンケート結果を ○ は 1 で×は 0 で表し,空白で区切られた m 個の数字が並んでいる.1 ≤ n ≤ 1000, 1 ≤ m ≤ 100 とする.

入力例１

4 6

1 0 1 0 1 1

1 1 0 1 0 0

1 1 1 0 0 0

1 0 1 0 1 0

出力例１

1 3 2 5 4 6

入力

入力は複数のデータセットからなる．n, m がともに 0 のとき入力が終了する．データセットの数は 5 を超えない．

出力

データセットごとに、場所の番号 を１行に出力する．

入力例

4 6
1 0 1 0 1 1
1 1 0 1 0 0
1 1 1 0 0 0
1 0 1 0 1 0
4 6
1 0 1 0 1 1
1 1 0 1 0 0
1 1 1 0 0 0
1 0 1 0 1 0
0 0

出力例

1 3 2 5 4 6
1 3 2 5 4 6

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


#include<stdio.h>
int main(void){
	int n,k,i,j,ans,sum;
	int a[100000];

	while(1){
		scanf("%d%d",&n,&k);
		if(!n && !k) break;
		ans=sum=0;

		for(i=0;i<n;i++){
			scanf("%d",&a[i]);
		}

		for(i=0;i<n-k;i++){
			for(j=0;j<k;j++){
				sum+=a[i+j];
			}
			if(sum>ans){
				ans=sum;
				sum=0;
			}
			else sum=0;
		}

		printf("%d\n",ans);
	}
	return 0;
}

最大の和

問題

n 個の整数からなる数列 a1, a2, ..., an と正整数 k (1 ≤ k ≤ n) が与えられる.このとき, 連続して並ぶ k 個の整数の和 Si = ai + ai+1 + ... + ai+k-1 (1 ≤ i ≤ n - k + 1) の最大値を出力するプログラムを作りなさい.

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．入力は２つのゼロを含む行で終了する．

1 行目には正整数 n (1 ≤ n ≤ 100000) と正整数 k (1 ≤ k ≤ n) がこの順に空白で
区切られて書かれている.2 行目以降の第 1 + i 行目 (1 ≤ i ≤ n) には, 数列の i 番目の項 ai (-10000 ≤ ai ≤ 10000) が書かれている.
採点用データのうち, 配点の 60% 分は n ≤ 5000, k ≤ 1000 を満たす.

データセットの数は 5 を超えない．

出力

データセットごとにSi の最大値を１行に出力する．

入出力例

入力例

5 3
2
5
-4
10
3
0 0

出力例

11

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


#include <stdio.h>

int main(void){
  int c1,c2;
  int i,j,n;
  int ans;
  int max_index;
  int num[100000];

  while(1){
    scanf("%d %d",&c1,&c2);
    if(c1 == 0 && c2 == 0){
      break;
    }
    ans = 0;
    max_index = c1 - c2;
    c1 -=1;

    for(i = 0;i <= c1;i++){
      scanf("%d",num+i);
    }

    for(i = 0;i <= max_index;i++){
      for(j = 1;j < c2;j++){
	num[i] += num[i+j];
      }
      if(num[i] > ans){
	n = i;
      }
    }

    printf("%d\n",num+n);
  }
  return 0;
}


#include<stdio.h>
#include<string.h>
#define min(a,b) (a<b?a:b)
struct x{int p,q,r,b;}B[105];
int N,i,j,h[105],r,t;

int gcd(int a,int b)
{
	int c;
	for(;b!=0;)
	{
		c=a%b;a=b;b=c;
	}
	return a;
}

int dfs(int p)
{
	int r,b,i,j,ta,tb,ri,rj,t1,t2;
	if(p==-1)return 1;
	if(h[p]>=0)return h[p];
	r=dfs(B[p].r);
	b=dfs(B[p].b);
	t1=10000000/(r*B[p].p),t2=10000000/(b*B[p].q);
	i=j=-1;
	ri=t1;
	rj=t2;
	for(i=1;i<=min(t1,t2);i++)
	{
		if((r*i*B[p].p)%(b*B[p].q))continue;
		j=(r*i*B[p].p)/(b*B[p].q);
		ta=r*i/B[p].q;
		tb=b*j/B[p].p;
		if(ta&&tb&&ta==tb)
		{
			if(ri*r+rj*b>i*r+j*b)
			{
				ri=i;
				rj=j;
			}
		}
	}
	if(j==-1)ri=rj=(r*b)/gcd(r,b);
	//printf("%d %d:%d %d:%d %d:%d\n",p,r,b,B[p].p,B[p].q,r*ri,b*rj);
	return h[p]=r*ri+b*rj;
}

int main()
{
	for(;scanf("%d",&N),N;)
	{
		memset(h,-1,sizeof(h));
		for(i=0;i<N;i++)
		{
			scanf("%d%d%d%d",&B[i].p,&B[i].q,&B[i].r,&B[i].b);
			t=gcd(B[i].p,B[i].q);
			B[i].p/=t;B[i].q/=t;
			B[i].r--;B[i].b--;
		}
		for(i=r=0;i<N;i++)
		{
			t=dfs(i);
			r=r>t?r:t;
		}
		printf("%d\n",r);
	}
	return 0;
}

最軽量のモビール

問題

モビールは動く芸術品として広く親しまれている.IOI 日本委員会では,JOI を広報するためにモビールを作成することになった.JOI 広報用モビールは,棒,紐(ひも),錘(おもり)の 3 種類の要素を用いて,次のように構成される.

棒の一方の端は青に,もう一方の端は赤に塗られている.

棒は両端以外の 1 箇所を支点として紐でつるされる.

支点から赤の端までの長さも支点から青の端までの長さも正整数である.

棒の両端には,紐で錘か他の棒をつるす.

錘は紐を用いてどれかの棒の一端につるされる.

錘には何もつるさない.

錘の重さは正整数である.

紐のうち 1 本だけは,片方の端をある棒をつるすためにその棒の支点に結ばれ,
もう一方の端は他のどの構成要素とも結ばれていない.他の紐は全て次のいず
れかを満たす.

ある棒の端とある棒の支点を結ぶ.

ある棒の端とある錘を結ぶ.

ただし,どの棒においても,バランスが取れている必要がある.棒と紐の重さは無視できるほど軽いので,棒と紐の重さは全て 0 であるとみなして解答せよ.つまり,それぞれの棒について,

(その棒の赤の端より下につるされている錘の重さの総計)
× (その棒の支点から赤の端までの長さ)
= (その棒の青の端より下につるされている錘の重さの総計)
× (その棒の支点から青の端までの長さ)

であるとき,その棒はバランスが取れているとせよ.

どのような長さの棒をどのように結びモビールを構成するかは既に決まっているのだが,錘の重さがまだ決まっていない.モビールは軽い方がつりやすいため, なるべく軽いモビールを作りたい.前述したようにどの棒もバランスを取りながら, モビールの総重量を最小にするような錘の付け方を求め, そのときのモビールの総重量を出力するプログラムを作れ. プログラムには以下のモビールの構成に関する情報が与えられる.

棒の本数 n

各棒ごとの情報(棒の番号は 1 から n)

支点から赤の端までの長さと支点から青の端までの長さの比

赤の端につるす棒の番号 (錘をつるす場合は 0)

青の端につるす棒の番号 (錘をつるす場合は 0)

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．入力はゼロ１つを含む行で終了する．

1 行目にはモビールに使われている棒の本数 n が書かれている.続く n 行 (1 ≤ n ≤ 100) には,各々の棒のデータが書かれている.i + 1 行目 (1 ≤ i ≤ n) には,4 つの整数 p, q, r, b が空白を区切りとして書かれており,棒 i において,支点から赤の端までの長さと支点から青の端までの比が p : q であり,赤の端につるされる棒の番号が r であり,青の端につるされる棒の番号が b であることを表している.ただし,棒番号 0 は錘がつるされることを表している.また,どの入力においても,モビールの重量の最小値を w とし,入力中で比を表すのに用いられる正整数の最大値を L とすると,wL < 231 を満たす.

データセットの数は 15 を超えない．

出力

データセットごとにモビールの重量を１行に出力する．

入出力例

入力例

1
6 9 0 0
4
3 2 0 4
1 3 0 0
4 4 2 1
2 2 0 0
0

出力例

5
40

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


#include<stdio.h>
#include<stdlib.h>
#define RMAX 10
#define CMAX 10000
int main(void){
	int R,C;
	char *Buffer=NULL;
	int Osenbei[RMAX][CMAX];
	int RSum[RMAX],CSum[CMAX];
	int count,count2,GoodSenbei=0;
	int BE_R=0;
	int Best=0,ans;

	//入力

	while(1){
		//行列サイズ入力
		scanf("%d %d%*c",&R,&C);
		if(R==0&&C==0){return 0;}//終了判定
		for(count=0;count<R;count++){//一行ずつ入力処理
			int InC=0,Charbuff=0;
			while(Charbuff=getchar()){//一文字ずつ入力
				if(Charbuff=='\n'){break;}
				else if(Charbuff=='0'){
					Osenbei[count][InC]=0;
					InC++;
				}
				else if(Charbuff=='1'){
					Osenbei[count][InC]=1;
					InC++;
				}
			}/*
			for(InC=0;InC<C;InC++){
				RSum[count]+=Osenbei[count][InC];
				CSum[InC]+=Osenbei[count][InC];
			}*/
			//for(InC=0;InC<C;InC++){
			//	printf("%d ",Osenbei[count][InC]);
			//}
		}
		//for(count2=-1;count2<C;count2++){
		//	printf("%d ",(count2==-1)?'/':CSum[count2]);
		//}
		//for(count=0;count<R;count++){
		//	printf("\n%d|",RSum[count]);
		//	for(count2=0;count2<C;count2++){
		//		printf("%d ",Osenbei[count][count2]);
		//	}
		//}puts("");
		//ここで全探索
		ans=0;
		for(count=0;count<(1<<R);count++){//全探索 裏返すのは1そうでないのは0
			int Best=0;
			for(count2=0;count2<C;count2++){
				int count3;
				int c_sum=0;
				for(count3=0;count3<R;count3++){
					c_sum+=(count&(1<<count3))?!(Osenbei[count3][count2]):Osenbei[count3][count2];

				}
				//printf("%d,",c_sum);
				Best+=(c_sum>(R>>1))?c_sum:R-c_sum;

			}
			//printf("|%d",Best);
			//puts("");
			ans=(Best>ans)?Best:ans;
		}
		printf("%d\n",ans);
	}
	return 0;

}

//次回　6/4

おせんべい

問題

IOI製菓では，創業以来の伝統の製法で煎餅（せんべい）を焼いている．この伝統の製法は，炭火で一定時間表側を焼き，表側が焼けると裏返して，炭火で一定時間裏側を焼くというものである．この伝統を守りつつ，煎餅を機械で焼いている．この機械は縦 R (1 ≤ R ≤ 10) 行, 横 C (1 ≤ C ≤ 10000) 列の長方形状に煎餅を並べて焼く．通常は自動運転で，表側が焼けたら一斉に煎餅を裏返し裏側を焼く．

ある日，煎餅を焼いていると，煎餅を裏返す直前に地震が起こり何枚かの煎餅が裏返ってしまった．幸いなことに炭火の状態は適切なままであったが，これ以上表側を焼くと創業以来の伝統で定められている焼き時間を超えてしまい，煎餅の表側が焼けすぎて商品として出荷できなくなる．そこで，急いで機械をマニュアル操作に変更し，まだ裏返っていない煎餅だけを裏返そうとした．この機械は，横の行を何行か同時に裏返したり縦の列を何列か同時に裏返したりすることはできるが，残念なことに，煎餅を１枚ごと裏返すことはできない．

裏返すのに時間がかかると，地震で裏返らなかった煎餅の表側が焼けすぎて商品として出荷できなくなるので，横の何行かを同時に１回裏返し，引き続き，縦の何列かを同時に１回裏返して，表側を焼きすぎずに両面を焼くことのできる煎餅，つまり，「出荷できる煎餅」の枚数をなるべく多くすることにした．横の行を１行も裏返さない，あるいは，縦の列を１列も裏返さない場合も考えることにする．出荷できる煎餅の枚数の最大値を出力するプログラムを書きなさい．

地震の直後に，煎餅が次の図のような状態になったとする．黒い丸が表側が焼ける状態を，白い丸が裏側が焼ける状態を表している．

1行目を裏返すと次の図のような状態になる．

さらに， 1列目と5列目を裏返すと次の図のような状態になる．この状態では，出荷できる煎餅は9枚である．

ヒント

R の上限 10 は C の上限 10000 に比べて小さいことに注意せよ．

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．

入力の1行目には2つの整数 R, C (1 ≤ R ≤ 10, 1 ≤ C ≤ 10 000) が空白を区切りとして書かれている．続く R 行は地震直後の煎餅の状態を表す． (i+1) 行目 (1 ≤ i ≤ R) には， C 個の整数 ai,1, ai,2, ……, ai,C が空白を区切りとして書かれており， ai,j は i 行 j 列 の煎餅の状態を表している. ai,j が 1 なら表側が焼けることを， 0 なら裏側が焼けることを表す．

C, R がともに 0 のとき入力の終了を示す.　データセットの数は 5 を超えない．

出力

データセットごとに，出荷できる煎餅の最大枚数を1行に出力する．

入出力例

入力例

2 5
0 1 0 1 0
1 0 0 0 1
3 6
1 0 0 0 1 0
1 1 1 0 1 0
1 0 1 1 0 1
0 0

出力例

9
15

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


#include <stdio.h>
#include <stdlib.h>

int comp(const void *a,const void *b);
int searchSup4(int P[],int N,int M);

int main(){

	int N,M,N0;	//1<=N<=1000;1<=N<=2E8
	int P0[1001];
	int P[1001];
	int i,j;
	int bak;
	int score_all;

	while(1){
		scanf("%d %d\n",&N0,&M);
		if(!N0&&!M)break;
		for(i=0;i<N0;i++)scanf("%d\n",&P0[i]);
		P0[N0]=0;

		qsort(P0,N0+1,sizeof(int),comp);
		P[0]=0;
		bak=0;
		N=N0;
		j=1;
		for(i=1;i<=N0;i++){
			if(P0[i]==bak){
				N--;
			}else{
				bak=P0[i];
				P[j]=P0[i];
				j++;
			}
		}

		score_all=searchSup4(P,N,M);
		printf("%d\n",score_all);

	}
	return 0;
}

int comp(const void *a,const void *b){
	int x= *(int *)a;
	int y= *(int *)b;
	return x>y?1:(x<y?-1:0);
}

int searchSup4(int P[],int N,int M){

	int PP[1001*1001/2];
	int i,j,NN;

	NN=0;
	for(i=0;i<=N;i++){
		for(j=i;j<=N;j++){
			if(P[i]+P[j]<=M){
				PP[NN]=P[i]+P[j];
				NN++;
			}
		}
	}

	qsort(PP,NN,sizeof(int),comp);

	int ans;

	ans=0;
	for(i=0;i<NN;i++){
		for(j=i;j<NN;j++){
			if(ans<=PP[i]+PP[j] && PP[i]+PP[j]<=M){
				ans=PP[i]+PP[j];
			}
		}
	}

	return ans;

}

ダーツ

問題

あなたは以下のルールでダーツゲームをすることになった.

あなたは,矢を的(まと)に向かって 4 本まで投げることができる.必ずしも 4 本全てを投げる必要はなく,1 本も投げなくてもかまわない.的は N 個の部分に区切られていて,各々の部分に点数 P1,..., PN が書か れている.矢が刺さった場所の点数の合計 S があなたの得点の基礎となる.S があらかじめ決められたある点数 M 以下の場合は S がそのままあなたの得点となる.しかし,S が M を超えた場合はあなたの得点は 0 点となる.

的に書かれている点数と M の値が与えられたとき,あなたが得ることのできる点数の最大値を求めるプログラムを作成せよ.

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．

1 行目には,整数 N (1 ≤ N ≤ 1000) と M (1 ≤ M ≤ 200000000 = 2 × 108)がこの順に空白区切りで書かれている.2 行目以降の第 1 + i 行目 (1 ≤ i ≤ N ) には, Pi (1 ≤ Pi ≤ 100000000 = 108 ) が書かれている.

採点用データのうち, 配点の 20% 分は N ≤ 100 を満たし,配点の 50% 分はN ≤ 300 を満たす.

N, M がともに 0 のとき入力の終了を示す. データセットの数は 10 を超えない．

出力

データセットごとにあなたが得ることのできる点数の最大値を１行に出力する.

入出力例

入力例

4 50
3
14
15
9
3 21
16
11
2
0 0

出力例

48
20

1つ目の例では,15 点の部分に 3 本,3 点の部分に 1 本の矢が刺さった場合にあなたの得点は最大になり,その得点は 48 点である.

2つ目の例では,16 点の場所に 1 本,2 点の場所に 2 本の矢が刺さった場合にあなたの得点は最大になり,その得点は 20 点である.

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char m[1002][1002];
char r[1002][1002];
struct node {
  unsigned x:10;
  unsigned y:10;
  unsigned int l;
  struct node* n;
} *qs,*qe;
typedef struct node st;
void push(int x,int y,int l)
{
  st *p = qe;
  if(qe == NULL){
    qe = (st *)(malloc(sizeof(st)));;
    qs = qe;
  }else{
    p->n = (st *)(malloc(sizeof(st)));
    qe = p->n;
  }
  qe->x = x;
  qe->y = y;
  qe->l = l;
  qe->n = NULL;
  r[y][x] = 1;
}
st *pop()
{
  st *p = qs;
  if(qs == NULL) return NULL;
  qs = qs->n;
  if(qs == NULL) qe = NULL;
  return p;
}
void flush()
{
  st *p = qs;
  while(p != NULL){
    qs = qs->n;
    free(p);
    p = qs;
  }
  qe = NULL;
}
int search(int* xs,int* ys,int d)
{
  st *p;
  int l,i,x,y;
  int xd[] = {-1,1,0,0}, yd[] = {0,0,-1,1};
  memset(r,0,sizeof(r));
  push(*xs,*ys,0);
  while((p = pop()) != NULL){
    for(i=0; i<4; i++) {
      x = (p->x) + xd[i];
      y = (p->y) + yd[i];
      if(m[y][x] == d) {
	*xs = x;
	*ys = y;
	l = (p->l) + 1;
	free(p);
	return l;
      }
      if((m[y][x] != -1) && (r[y][x] == 0))
	push(x, y, (p->l)+1);
    }
    free(p);
  }
}
int main(){
  int h,w,n,i,j,xs,ys,t=0;
  char c[1002];
  memset(m,-1,sizeof(m));
  scanf("%d%d%d\n",&h,&w,&n);
  for(i=1;i<=h;i++){
    scanf("%s",c);
    for(j=1;j<=w;j++){
      switch(c[j-1]){
      case 'S':
	xs = j; ys = i;
      case '.':
	m[i][j] = 0;
	break;
      case 'X':
	m[i][j] = -1;
	break;
      default:
	m[i][j] = c[j-1]-'0';
      }
    }
    scanf("\n");
  }
  for(i=1;i<=n;i++){
    t+=search(&xs,&ys,i);
    flush();
  }
  printf("%d\n",t);
  return 0;
}

チーズ (Cheese)

問題

今年も JOI 町のチーズ工場がチーズの生産を始め，ねずみが巣から顔を出した．JOI 町は東西南北に区画整理されていて，各区画は巣，チーズ工場，障害物，空き地のいずれかである．ねずみは巣から出発して全てのチーズ工場を訪れチーズを 1 個ずつ食べる．

この町には，N 個のチーズ工場があり，どの工場も１種類のチーズだけを生産している．チーズの硬さは工場によって異なっており，硬さ 1 から N までのチーズを生産するチーズ工場がちょうど 1 つずつある．

ねずみの最初の体力は 1 であり，チーズを 1 個食べるごとに体力が 1 増える．ただし，ねずみは自分の体力よりも硬いチーズを食べることはできない．

ねずみは，東西南北に隣り合う区画に 1 分で移動することができるが，障害物の区画には入ることができない．チーズ工場をチーズを食べずに通り過ぎることもできる．すべてのチーズを食べ終えるまでにかかる最短時間を求めるプログラムを書け．ただし，ねずみがチーズを食べるのにかかる時間は無視できる．

入力

入力は H+1 行ある．1 行目には 3 つの整数 H，W，N (1 ≤ H ≤ 1000，1 ≤ W ≤ 1000，1 ≤ N ≤ 9) がこの順に空白で区切られて書かれている．2 行目から H+1 行目までの各行には，'S'，'1', '2', ..., '9'，'X'，'.' からなる W 文字の文字列が書かれており，各々が各区画の状態を表している．北から i 番目，西から j 番目の区画を (i,j) と記述することにすると (1 ≤ i ≤ H, 1 ≤ j ≤ W)，第 i+1 行目の j 番目の文字は，区画 (i,j) が巣である場合は 'S' となり，障害物である場合は 'X' となり，空き地である場合は '.' となり，硬さ 1, 2, ..., 9 のチーズを生産する工場である場合はそれぞれ '1', '2', ..., '9' となる．入力には巣と硬さ 1, 2, ..., N のチーズを生産する工場がそれぞれ 1 つずつある．他のマスは障害物または空き地であることが保証されている．ねずみは全てのチーズを食べられることが保証されている．

出力

すべてのチーズを食べ終えるまでにかかる最短時間（分）を表す整数を 1 行で出力せよ．

入出力例

入力例 1

3 3 1
S..
...
..1

出力例 1

4

入力例 2

4 5 2
.X..1
....X
.XX.S
.2.X.

出力例 2

12

入力例 3

10 10 9
.X...X.S.X
6..5X..X1X
...XXXX..X
X..9X...X.
8.X2X..X3X
...XX.X4..
XX....7X..
X..X..XX..
X...X.XX..
..X.......

出力例 3

91

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


#include <stdio.h>
#include <string.h>

int main (void){

	int i=0;
	int number=0;
	int input[100000]={0};
	int x=1;
	int y=1;
	int s=0;
	int count=0;
	int flag=0;

	scanf("%d",&number);

	if (number > 100000){
		return 1;
	}

	for ( i=0; i < number; i++){
		scanf("%d", &input[i]);
		if ( input[i] > 2147483647){
			return 1;
		}
	}

	i=0;

	while(1){
		flag =1;
		int x_hold =1;
		int y_hold=1;

		for ( x= x_hold; x <= (input[i]-1)/3; x++){
			for(y=y_hold; y<=x; y++){
				if( (2 * x * y + x + y) == input[i]){
					flag=0;
					x_hold = x;
					y_hold = y;
					break;
					break;
				}
				if( (2 * x * y + x + y) > input[i]){
					break;
					break;
				}
			}
		}
		i++;
		if(flag == 1){
			count++;
			flag=0;
		}

		if(i== number){
			break;
		}
	}

	printf("%d\n",count );

	/*

	while (1){
		s = 2 * x * y + x + y;
		//11:4
		//21:7
		//31:10
		//41:13
		//22:12
		//32:17
		//33:

		if (input[i] > s){
			if(x <= y ){
				x++;
				continue;
			}
			y++;
			continue;
		}

		else if (input[i] < s ){
			count++;
			i++;
		}

		else if (input[i] == s){
			i++;
		}

		if(i==number){
			break;
		}

	}
	*/

	return 0;
}

問題 4

　IOI 不動産ではマンションの賃貸を行なっている．
この会社が取り扱うマンションの部屋は 1LDK で，
下図のように面積が 2xy+x+y になっている．
ただし， x, y は正整数である．

　IOI 不動産のカタログにはマンションの面積が昇順に（狭いものから順番に）書かれているが，この中にいくつか間違い（ありえない面積のもの）が混じっていることがわかった．

　カタログ（入力ファイル）は N+1 行で，最初の行に部屋数が書かれていて，
続く N 行に，１行に１部屋ずつ面積が昇順に書かれている．
ただし，
部屋数は 100,000 以下，
面積は (2の31乗)-1 = 2,147,483,647 以下である．
５つの入力データのうち３つまでは，
部屋数 1000 以下，面積 30000 以下である．

　間違っている行数（ありえない部屋の数）を出力しなさい．

　出力ファイルにおいては，
出力の最後の行にも改行コードを入れること．

入出力例

入力例

10
4
7
9
10
12
13
16
17
19
20

出力例

2

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


// AOJ 	0601 Sugar Glider
// 2018.1.16 bal4u

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define QMAX 350000
typedef struct { long long t; int s; } QUE;
QUE que[QMAX]; int qsize;

#define PARENT(i) ((i)>>1)
#define LEFT(i)   ((i)<<1)
#define RIGHT(i)  (((i)<<1)+1)

void max_heapify(int i)
{
	int l, r, max;
	QUE qt;
	l = LEFT(i), r = RIGHT(i);
	if (l < qsize && que[l].t > que[i].t) max = l; else max = i;
	if (r < qsize && que[r].t > que[max].t) max = r;
	if (max != i) {
		qt = que[i], que[i] = que[max], que[max] = qt;
		max_heapify(max);
	}
}

void deq()
{
	que[0] = que[--qsize];
	max_heapify(0);
}

void enq(int s, long long t)
{
	int i, max;
	QUE qt;

	i = qsize++;
	que[i].s = s, que[i].t = t;
	while (i > 0 && que[max = PARENT(i)].t < que[i].t) {
		qt = que[i]; que[i] = que[max], que[max] = qt;
		i = max;
	}
}

typedef struct { int a, b, t; } T;
T tbl[300002];

int h[100002];
int *to[100002], *dt[100002], hi[100002];
char used[100002];

//#define getchar_unlocked()  getchar()
int in()
{
	int n = 0;
	int c = getchar_unlocked();
	do n = (n<<3)+(n<<1) + (c & 0xf), c = getchar_unlocked();
	while (c >= '0');
	return n;
}

long long dijkstra(int start, int goal, int val)
{
	int i, s, e, c;
	long long d, x;

	qsize = 0;
	enq(start, val);
	while (qsize) {
		s = que[0].s, d = que[0].t, deq();
		if (s == goal) return val + h[goal] - d*2;
		if (used[s]) continue;
		used[s] = 1;
		for (i = 0; i < hi[s]; i++) {
			e = to[s][i];
			c = dt[s][i];
			if (used[e] || c > h[s]) continue;
			x = d - c; if (x > h[e]) x = h[e];
			enq(e, x);
		}
	}
	return -1;
}

int main()
{
	int n, m, x;
	int i, k;
	T *tp;

	n = in(), m = in(), x = in();
	for (i = 0; i < n; i++) h[i] = in();
	for (tp = tbl, i = 0; i < m; i++, tp++) {
		tp->a = in()-1, tp->b = in()-1, tp->t = in();
		hi[tp->a]++, hi[tp->b]++;
	}
	for (i = 0; i < n; i++) {
		to[i] = malloc(hi[i] << 2);
		dt[i] = malloc(hi[i] << 2);
	}
	memset(hi, 0, sizeof(hi));
	for (tp = tbl, i = 0; i < m; i++, tp++) {
		k = hi[tp->a]++, to[tp->a][k] = tp->b, dt[tp->a][k] = tp->t;
		k = hi[tp->b]++, to[tp->b][k] = tp->a, dt[tp->b][k] = tp->t;
	}
	printf("%lld\n", dijkstra(0, n-1, x));
	return 0;
}

MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

フクロモモンガ(Sugar Glider)

フクロモモンガのJOI 君が住んでいる森にはユーカリの木が $N$ 本生えており，それらの木には1 から $N$ の番号がついている．木 $i$ の高さは $H_i$ メートルである．

JOI 君が相互に直接飛び移ることのできる木の組が $M$ 組あり，各組の木の間を飛び移るためにかかる時間が定まっている．JOI 君が木の間を飛び移っている間は，地面からの高さが1 秒あたり1 メートル下がる．すなわち，JOI 君の現在の地面からの高さが $h$ メートル，木の間を飛び移るためにかかる時間が $t$ 秒であるとき，飛び移った後の地面からの高さは $h - t$ メートルとなる．ただし，$h - t$ が0 よりも小さくなる場合や行き先の木の高さよりも大きくなる場合は飛び移ることができない．

さらに，JOI 君は木の側面を上下に移動することによって，地面からの高さを0 メートルから今いる木の高さの範囲で増減させることができる．JOI 君が地面からの高さを1 メートル増加または減少させるためには1 秒の時間がかかる．

JOI 君は，木1 の高さ$X$ メートルの位置から木$N$ の頂上(高さ$H_N$ メートルの位置) に行こうとしており，そのためにかかる時間の最小値を知りたい．

課題

各木の高さと，JOI 君が直接飛び移ることができる木の組の情報と，最初JOI 君がいる場所の高さが与えられる．木 $N$ の頂上に行くためにかかる時間の最小値を求めるプログラムを作成せよ.

入力

標準入力から以下のデータを読み込め．

1 行目には，整数 $N, M, X$ が空白を区切りとして書かれている．これは，木の本数が $N$ 本，移動できる木の組が $M$ 組あり，最初JOI 君が木1 の高さ $X$ メートルの位置にいることを表す．

続く $N$ 行のうちの $i$ 行目$(1 \leq i \leq N)$ には，整数 $H_i$ が書かれている．これは，木 $i$ の高さが $H_i$ メートルであることを表す．

続く$M$ 行のうちの $j$ 行目$(1 \leq j \leq M)$ には，整数 $A_j, B_j, T_j$ $(1 \leq A_j \leq N, 1 \leq B_j \leq N, A_j \ne B_j)$ が空白を区切りとして書かれている．これは，木 $A_j$ と木 $B_j$ の間を相互に $T_j$ 秒で飛び移ることができることを表している．また，$1 \leq j < k \leq M$ ならば，$(A_j, B_j) \ne (A_k, B_k)$ および$(A_j, B_j) \ne (B_k, A_k)$ を満たす．

出力

標準出力に，木1 の高さ $X$ メートルの位置から木 $N$ の頂上に行くためにかかる時間の最小値を秒単位で表す整数を1 行で出力せよ．ただし，そのような方法がない場合は代わりに -1 を出力せよ．

制限

すべての入力データは以下の条件を満たす．

$2 \leq N \leq 100000$

$1 \leq M \leq 300000$

$1 \leq H_i \leq 1000000000 (1 \leq i \leq N)$

$1 \leq T_j \leq 1000000000 (1 \leq j \leq M)$

$0 \leq X \leq H_1$

入出力例

入力例 1

5 5 0
50
100
25
30
10
1 2 10
2 5 50
2 4 20
4 3 1
5 4 20

出力例 1

110

例えば，以下のように移動すればよい．

1. 木1 を50 メートル登る．

2. 木1 から木2 に飛び移る．

3. 木2 から木4 に飛び移る．

4. 木4 から木5 に飛び移る．

5. 木5 を10 メートル登る．

入力例 2

2 1 0
1
1
1 2 100

出力例 2

-1

JOI 君は木1 から木2 に飛び移ることができない．

入力例 3

4 3 30
50
10
20
50
1 2 10
2 3 10
3 4 10

出力例 3

100

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。


// AOJ 1008: What Color Is The Universe?
// 2017.8.19 bal4u@uu
// 2017.11.9 retry

#include <stdio.h>
#include <string.h>

#define HASHSIZ 120011
typedef struct { int n, c; } HASH;
HASH hash[HASHSIZ+2], *hashend = hash+HASHSIZ;

int color, cnt;

int lookup(int n)
{
	HASH *p = hash + n % HASHSIZ;
	while (p->n) {
		if (p->n == n) return ++(p->c);
		if (++p == hashend) p = hash;
	}
	p->n = n, p->c = 1;
	return 1;
}

char buf[11000000], *p;
int getint()
{
	int n = 0;
	while (*p >= '0') n = (n<<3) + (n<<1) + (*p++ & 0xf);
	return n;
}

int main()
{
	int n, n2, i, k;

	while (fgets(p=buf, 20, stdin) && *p != '0') {
		n = getint(), n2 = n >> 1;
		memset(hash, 0, sizeof(hash));
		fgets(p=buf, sizeof(buf), stdin);
		for (cnt = 1, i = n; i--; ) {
			k = getint(), p++;
			if (lookup(k) == cnt) cnt++, color = k;
		}
		if (--cnt > n2) printf("%d\n", color);
		else puts("NO COLOR");
	}
	return 0;
}

What Color Is The Universe?

On a clear night, a boy, Campanella looked up at the sky, there were many stars which have different colors such as red, yellow, green, blue, purple, etc. He was watching the stars and just lost track of time. Presently, he wondered,

"There are many stars in the space. What color is the universe if I look up it from outside?"

Until he found the answer to this question, he couldn't sleep. After a moment's thought, he proposed a hypothesis,

"When I observe the stars in the sky, if more than half of the stars have the same color, that is the color of the universe."

He has collected data of stars in the universe after consistently observing them. However, when he try to count the number of star, he was in bed sick with a cold. You decided to help him by developing a program to identify the color of the universe.

You are given an array A. Let |A| be the number of element in A, and let Nm be the number of m in A. For example, if A = {3, 1, 2, 3, 3, 1, 5, 3}, |A| = 8, N3 = 4, N1 = 2, N5 = 1. Your program have to find m such that:

Nm > (|A| / 2 )

If there is no such m, you also have to report the fact. There is no
such m for the above example, but for a array A = {5, 2, 5, 3, 4, 5, 5}, 5 is the answer.

Input

There are several test cases. For each test case, in the first line |A| is given. In the next line, there will be |A| integers. The integers are less than 231 and |A| < 1,000,000. The input terminate with a line which contains single 0.

Output

For each test case, output m in a line. If there is no answer, output "NO COLOR" in a line.

Sample Input

8
3 1 2 3 3 1 5 3
7
5 2 5 3 4 5 5
0

Output for the Sample Input

NO COLOR
5


Problem G: Dominating Set

What you have in your hands is a map of Aizu-Wakamatsu City. The lines on this map represent streets and the dots are street corners. Lion Dor Company is going to build food stores at some street corners where people can go to buy food. It is unnecessary and expensive to build a food store on every corner. Their plan is to build the food stores so that people could get food either right there on the corner where they live, or at the very most, have to walk down only one street to find a corner where there was a food store. Now, all they have to do is figure out where to put the food store.

The problem can be simplified as follows. Let G = (V, E) be unweighted undirected graph. A dominating set D of G is a subset of V such that every vertex in V - D is adjacent to at least one vertex in D. A minimum dominating set is a dominating set of minimum number of vertices for G. In the example graph given below, the black vertices are the members of the minimum dominating sets.

Design and implement an algorithm for the minimum domminating set problem.

Input

Input has several test cases. Each test case consists of the number of nodes n and the number of edges m in the first line. In the following m lines, edges are given by a pair of nodes connected by the edge. The graph nodess are named with the numbers 0, 1,..., n - 1 respectively.

The input terminate with a line containing two 0. The number of test cases is less than 20.

Constrants

n ≤ 30

m ≤ 50

Output

Output the size of minimum dominating set for each test case.

Sample Input

5 4
0 1
0 4
1 2
3 4
5 4
0 1
0 4
1 2
3 4
0 0

Output for the Sample Input

2
2


Problem D: Dr. Nakamura's Lab.

Dr.中村は偉大な発明者である, 今日も常人には発想出来ない新たな発明に取り掛かっている. 今発明しているのは新たな防犯システムとコンテナである.

防犯システムの方は上に乗った者を識別して招かれざる客だった場合, 電流を流して気絶させるパネルである. このパネルは踏まないように上を通過しても無駄で, 空中のものに対し放電する. しかし, まだ完成には程遠く, 電流は強すぎて調節が不可能で, 一度放電すると充電しない限り使えない. また, 人と物体の区別ができず, そもそも人自体区別できない等欠点をあげればキリがない.

コンテナの方は謎の力によって常時地面から浮いており, 運ぶのに便利に作ってある. しかし, これも完成には遠く, 一度押すと何かにぶつかるまで止まらない.

Dr.中村は一日の作業を終え, 帰宅しようとしたが未完成のパネルを設置したままだということに気づいた. これを取り外すのは防犯上非常に困難に作ってある上に, これを通らなければ帰れないような位置に設置してしまったのでDr.中村は途方に暮れた. しかし, 素晴らしい頭脳を持つDr.中村は解決案をすぐに思いついた. パネルは一度放電させれば通れるようになるため, コンテナを通過させればパネルの上を通れるようになる, そう考えた. 実際, パネルの上にコンテナを通過させると, コンテナは電流によって消滅してしまう一方でパネルは放電し, 通れるようになる.

しかし, 研究室の中は入り組んでおり, うまくコンテナを動かさないとパネルを通過させられない. Dr.中村は助手であるあなたにメールで助けを求めた. あなたの仕事は研究室の情報が与えられた時にDr.中村が出口までたどり着くためのプログラムを作成することである.

研究室は二次元グリッドで与えられ, Dr.中村は一度の移動で上下左右に隣接するセルに移動することが出来る.ただし, 障害物, コンテナ, 放電していないパネルのセルには移動できない.

Dr.中村は上下左右に隣接するセルにあるコンテナを押すことができ, コンテナはDr.中村がいる方向と逆の方向に別のコンテナか障害物にぶつかる, あるいは放電されていないパネルの上を通過するまで動く. また, 何かにぶつかり止まった場合, ぶつかる直前のセルで静止する.

出口はコンテナもDr.中村も侵入可能である. コンテナは出口を通っても消滅せず、そのまま通過する.

壁にぶつかって出口をふさぐことはある. この場合は出口に進入できない.

あなたのプログラムが要求されていることは, Dr.中村は最少何回の移動で研究室を脱出できるかを出力することのみである. なぜなら, Dr.中村は素晴らしい頭脳の持ち主なのでそれさえわかれば自分で脱出するからである.

Input

入力は複数のデータセットからなり, 一行目に研究室の縦の長さ H と横の長さ W が与えられる.
2行目以降では研究室の状態が H × W 個の文字で表わされる. 各文字が表すものは以下のとおりである:

‘#’障害物を表す.

‘@’Dr.中村の初期位置を表す.

‘w’パネルを表す.

‘c’コンテナを表す.

‘.’何も置かれていない空白のセルを表す.

‘E’脱出口を表す.

縦と横の長さがともに 0 のとき入力の終了を表す. これについて処理をする必要はない.

以下のことを仮定してよい.

3 ≤ H, W ≤ 10

研究室の周囲は障害物で囲まれている.

パネルとコンテナの数はそれぞれ 3 を越えない.

研究室にはただ１つの出口がある.

Output

各データセットについて最少の移動回数を１行に出力せよ. なお、Dr.中村が脱出できない場合、”-1”と出力せよ.

Sample Input

5 5
#####
##@##
#wc.#
#Ew.#
#####
5 5
#####
##@.#
#wc.#
#E#.#
#####
3 6
######
#@.wE#
######
0 0

Output for the Sample Input

3
5
-1


#include <stdio.h>

int main(void){
    int a, b, t, i, j, k, ans, flg;

	while( scanf( "%d %d %d", &t, &a, &b ) != EOF ) {
		ans = 0;
		if( !(t|a|b) ) break;
		for( k = 1; k <= t; k++ ) {
			flg = 0;
			for( i = 0; a*i <= k && flg == 0; i ++ )
				for( j = 0; a*i + b*j <= k && flg == 0; j++ ) {
					if( a*i + b*j == k ) {
						flg = 1;
						//printf("%d = %d * %d + %d * %d\n", k, a, i, b, j );
						ans ++;
					}
				}
		}
		printf("%d\n",t-ans);
	}

    return 0;
}

Unable Count

I would, if I could,

If I couldn't how could I?

I couldn't, without I could, could I?

Could you, without you could, could ye?

Could ye? could ye?

Could you, without you could, could ye?

It is true, as this old rhyme says, that we can only DO what
we can DO and we cannot DO what we cannot DO. Changing some of
DOs with COUNTs, we have another statement that we can only COUNT
what we can DO and we cannot COUNT what we cannot DO, which looks
rather false. We could count what we could do as well as we could
count what we couldn't do. Couldn't we, if we confine ourselves
to finite issues?

Surely we can count, in principle, both what we can do and
what we cannot do, if the object space is finite. Yet, sometimes
we cannot count in practice what we can do or what we cannot do.
Here, you are challenged, in a set of all positive integers up
to (and including) a given bound n, to count
all the integers that cannot be represented by a formula of
the form a*i+b*j, where a and
b are given positive integers and i and j
are variables ranging over non-negative integers. You are requested
to report only the result of the count, i.e. how many integers
are not representable.
For example, given n = 7, a = 2, b = 5,
you should answer 2, since 1 and 3 cannot be represented in a
specified form, and the other five numbers are representable as follows:

2 = 2*1 + 5*0, 4 = 2*2 + 5*0, 5 = 2*0 + 5*1,
6 = 2*3 + 5*0, 7 = 2*1 + 5*1.

Input

The input is a sequence of lines. Each line consists of three integers,
n, a and b, in this order, separated by a
space. The integers n, a and b are
all positive and at most one million, except those in the last
line. The last line consists of three zeros.

Output

For each input line except the last one, your program should
write out a line that contains only the result of the count.

Sample Input

10 2 3
10 2 5
100 5 25
0 0 0

Output for the Sample Input

1
2
80


Problem B: Organize Your Train part II

RJ Freight, a Japanese railroad company for freight operations
has recently constructed exchange lines at Hazawa, Yokohama.
The layout of the lines is shown in Figure B-1.

Figure B-1: Layout of the exchange lines

A freight train consists of 2 to 72 freight cars. There are 26
types of freight cars, which are denoted by 26 lowercase letters
from "a" to "z". The cars of the same type are indistinguishable from
each other, and each car's direction doesn't matter either.
Thus, a string of lowercase letters of length 2 to 72 is sufficient
to completely express the configuration of a train.

Upon arrival at the exchange lines, a train is divided into two
sub-trains at an arbitrary position (prior to entering the
storage lines). Each of the sub-trains may have its direction
reversed (using the reversal line). Finally, the two sub-trains
are connected in either order to form the final configuration.
Note that the reversal operation is optional for each of the
sub-trains.

For example, if the arrival configuration is "abcd", the train
is split into two sub-trains of either 3:1, 2:2 or 1:3 cars.
For each of the splitting, possible final configurations are
as follows ("+" indicates final concatenation position):

[3:1]
abc+d cba+d d+abc d+cba
[2:2]
ab+cd ab+dc ba+cd ba+dc cd+ab cd+ba dc+ab dc+ba
[1:3]
a+bcd a+dcb bcd+a dcb+a

Excluding duplicates, 12 distinct configurations are possible.

Given an arrival configuration, answer
the number of distinct configurations which can be
constructed using the exchange lines described above.

Input

The entire input looks like the following.

the number of datasets = m

1st dataset

2nd dataset

...

m-th dataset

Each dataset represents an arriving train, and is a string of
2 to 72 lowercase letters in an input line.

Output

For each dataset, output the number of possible train configurations
in a line. No other characters should appear in the output.

Sample Input

4
aa
abba
abcd
abcde

Output for the Sample Input

1
6
12
18


#include <stdio.h>
#include <string.h>

int main(void)
{
    int n, i;
    scanf("%d", &n);
    for(i = 0; i < n; i++){
        char done[1024][73];
        char org[73];
        int num = 0, len, j;

        scanf("%s", org);
        len = strlen(org);

        for(j = 1; j < len; j++){
            int k;
            char first[2][72], second[2][72];
            for(k = 0; k < j; k++){
                first[0][k] = first[1][j - 1 - k] = org[k];
            }
            first[0][k] = first[1][k] = '\0';
            for(k = j; k < len; k++){
                second[0][k - j] = second[1][len -1 - k] = org[k];
            }
            second[0][len - j] = second[1][len - j] = '\0';
            //printf("first: %s, rev: %s\n", first[0], first[1]);
            //printf("second: %s, rev: %s\n", second[0], second[1]);

            int l;
            for(k = 0; k < 2; k++){
                for(l = 0; l < 2; l++){
                    int m;
                    char temp[73];
                    strcpy(temp, first[k]);
                    strcat(temp, second[l]);
                    for(m = 0; m < num; m++)
                        if(strcmp(temp, done[m]) == 0)
                            break;
                    if(m == num){
                        strcpy(done[num], temp);
                        num++;
                    }
                    strcpy(temp, second[l]);
                    strcat(temp, first[k]);
                    for(m = 0; m < num; m++)
                        if(strcmp(temp, done[m]) == 0)
                            break;
                    if(m == num){
                        strcpy(done[num], temp);
                        num++;
                    }
                }
            }
        }
        //for(j = 0; j < num; j++)
        //    printf("%s\n", done[j]);

        printf("%d\n", num);
    }
    return 0;
}


#include "stdio.h"

int nyuu(int );

int sosu(int nyuu){
	int i;
	int count = 0;
	//printf("%d\n", nyuu);
	for(i = 0; i < 300000;i++){
		if(i % 7 == 6 || i % 7 == 1){
			if(nyuu % i == 0){
				count++;
			}
		}
	}
	if(count == 2){
		return nyuu;
	}
	else {
		return 0;
	}
}

int main(int argc, char const *argv[])
{
	int nyuuryoku;
	int i,j,k;
	int ans;
	while(1){
		scanf("%d",&nyuuryoku);
		if(nyuuryoku == 1){
			break;
		}
		printf("%d:", nyuuryoku);
		for(i = 0;i < 3000000;i++){
			if(i % 7 == 6 || i % 7 == 1){
				if(nyuuryoku % i == 0){
					ans = sosu(i);
					//printf("%d\n", ans);
					if(ans != 0){
						printf("%d ", ans);
					}
				}
			}
		}
		printf("\n");
	}
	return 0;
}

Problem B: Monday-Saturday Prime Factors

Chief Judge's log, stardate 48642.5.
We have decided to make a problem from elementary number theory.
The problem looks like finding all prime factors of a positive integer,
but it is not.

A positive integer whose remainder divided by 7 is either 1 or 6 is called
a 7N+{1,6} number.
But as it is hard to pronounce,
we shall call it a Monday-Saturday number.

For Monday-Saturday numbers a and b,
we say a is a Monday-Saturday divisor of b
if there exists a Monday-Saturday number x
such that ax = b.
It is easy to show that
for any Monday-Saturday numbers a and b,
it holds that a is
a Monday-Saturday divisor of b
if and only if
a is a divisor of b in the usual sense.

We call a Monday-Saturday number a Monday-Saturday prime
if it is greater than 1 and has no Monday-Saturday divisors
other than itself and 1.
A Monday-Saturday number which is a prime in the usual sense
is a Monday-Saturday prime
but the converse does not always hold.
For example, 27 is a Monday-Saturday prime
although it is not a prime in the usual sense.
We call a Monday-Saturday prime
which is a Monday-Saturday divisor of a Monday-Saturday number a
a Monday-Saturday prime factor of a.
For example, 27 is one of the Monday-Saturday prime factors of 216,
since 27 is a Monday-Saturday prime
and 216 = 27 × 8 holds.

Any Monday-Saturday number greater than 1
can be expressed as a product of one or more Monday-Saturday primes.
The expression is not always unique
even if differences in order are ignored.
For example,

216 = 6 × 6 × 6 = 8 × 27

holds.

Our contestants should write a program that outputs
all Monday-Saturday prime factors
of each input Monday-Saturday number.

Input

The input is a sequence of lines each of which contains a single
Monday-Saturday number.
Each Monday-Saturday number is greater than 1
and less than 300000 (three hundred thousand).
The end of the input is indicated by a line
containing a single digit 1.

Output

For each input Monday-Saturday number,
it should be printed, followed by a colon `:'
and the list of its Monday-Saturday prime factors on a single line.
Monday-Saturday prime factors should be listed in ascending order
and each should be preceded by a space.
All the Monday-Saturday prime factors should be printed only once
even if they divide the input Monday-Saturday number more than once.

Sample Input

205920
262144
262200
279936
299998
1

Output for the Sample Input

205920: 6 8 13 15 20 22 55 99
262144: 8
262200: 6 8 15 20 50 57 69 76 92 190 230 475 575 874 2185
279936: 6 8 27
299998: 299998


//SPFA
#include <stdio.h>
#include <string.h>
#define INF (9*900*4)
#define rep(i,n) for(i=0;i<(n);i++)
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};

struct Node{
	int y,x,dir;
};

void _a(struct Node *a){a->y+=dy[a->dir];a->x+=dx[a->dir];}
void _b(struct Node *a){a->dir=(a->dir+1)%4;_a(a);}
void _c(struct Node *a){a->dir=(a->dir+2)%4;_a(a);}
void _d(struct Node *a){a->dir=(a->dir-1+4)%4;_a(a);}
void _e(struct Node *a){}
void (*action[5])(struct Node *)={_a,_b,_c,_d,_e};

int in(int y,int x,int h,int w){
	return 0<=y&&y<h&&0<=x&&x<w;
}
int main(){
	struct Node a,b,que[INF];
	int head,tail;
	int inQ[30][30][4],dst[30][30][4];

	int w,h,s[30][30],c[4];
	int i,j,k,ans;
	while(scanf("%d%d",&w,&h)==2&&(w||h)){
		rep(i,h)
			rep(j,w)scanf("%d",&s[i][j]);
		rep(i,4)scanf("%d",c+i);
		memset(inQ,0,sizeof(inQ));
		rep(i,h)rep(j,w)rep(k,4)dst[i][j][k]=INF;
		a.y=a.x=a.dir=0;
		head=tail=0;
		dst[a.y][a.x][a.dir]=0;
		que[tail++]=a;
		while(head<tail){
			a=que[head++];
			inQ[a.y][a.x][a.dir]=0;
			b=a;
			action[s[b.y][b.x]](&b);
			if(in(b.y,b.x,h,w) && dst[a.y][a.x][a.dir] < dst[b.y][b.x][b.dir]){
				dst[b.y][b.x][b.dir] = dst[a.y][a.x][a.dir];
				if(inQ[b.y][b.x][b.dir]==0){
					que[tail++]=b;
					inQ[b.y][b.x][b.dir]=1;
				}
			}
			rep(i,4){
				b=a;
				action[i](&b);
				if(in(b.y,b.x,h,w) && dst[a.y][a.x][a.dir]+c[i] < dst[b.y][b.x][b.dir]){
					dst[b.y][b.x][b.dir] = dst[a.y][a.x][a.dir]+c[i];
					if(inQ[b.y][b.x][b.dir]==0){
						que[tail++]=b;
						inQ[b.y][b.x][b.dir]=1;
					}
				}
			}
		}
		ans=INF;
		rep(i,4){
			if(dst[h-1][w-1][i] < ans)ans = dst[h-1][w-1][i];
		}
		printf("%d\n",ans);
	}
}

Problem D: Twirling Robot

Let's play a game using a robot on a rectangular board
covered with a square mesh (Figure D-1).
The robot is initially set at the start square in the northwest corner
facing the east direction.
The goal of this game is to lead the robot
to the goal square in the southeast corner.

Figure D-1: Example of a board

The robot can execute the following five types of commands.

"Straight":

Keep the current direction of the robot, and move forward to the next square.

"Right":

Turn right with 90 degrees from the current direction, and move forward to the next square.

"Back":

Turn to the reverse direction, and move forward to the next square.

"Left":

Turn left with 90 degrees from the current direction, and move forward to the next square.

"Halt":

Stop at the current square to finish the game.

Each square has one of these commands assigned as shown in Figure D-2.
The robot executes the command assigned to the square where it resides,
unless the player gives another command to be executed instead.
Each time the player gives an explicit command,
the player has to pay the cost that depends on the command type.

Figure D-2: Example of commands assigned to squares

The robot can visit the same square several times during a game.
The player loses the game when the robot goes out of the board
or it executes a "Halt" command before arriving at the goal square.

Your task is to write a program that calculates the minimum cost to lead the robot
from the start square to the goal one.

Input

The input is a sequence of datasets.
The end of the input is indicated by a line containing two zeros separated by a space.
Each dataset is formatted as follows.

w h

s(1,1) ... s(1,w)

s(2,1) ... s(2,w)

...

s(h,1) ... s(h,w)

c0 c1 c2 c3

The integers h and w are the numbers of rows and columns of the board,
respectively.
You may assume 2 ≤ h ≤ 30 and 2 ≤ w ≤ 30.
Each of the following h lines consists of w numbers delimited by a space.
The number s(i, j) represents the command assigned to the square
in the i-th row and the j-th column as follows.

0: "Straight"

1: "Right"

2: "Back"

3: "Left"

4: "Halt"

You can assume that a "Halt" command is assigned to the goal square.
Note that "Halt" commands may be assigned to other squares, too.

The last line of a dataset contains four integers
c0, c1, c2, and c3, delimited by a space,
indicating the costs that the player has to pay
when the player gives
"Straight", "Right", "Back", and "Left" commands
respectively.
The player cannot give "Halt" commands.
You can assume that all the values of
c0, c1, c2, and c3
are between 1 and 9, inclusive.

Output

For each dataset, print a line only having a decimal integer indicating the minimum cost
required to lead the robot to the goal.
No other characters should be on the output line.

Sample Input

8 3
0 0 0 0 0 0 0 1
2 3 0 1 4 0 0 1
3 3 0 0 0 0 0 4
9 9 1 9
4 4
3 3 4 0
1 2 4 4
1 1 1 0
0 2 4 4
8 7 2 1
2 8
2 2
4 1
0 4
1 3
1 0
2 1
0 3
1 4
1 9 3 1
0 0

Output for the Sample Input

1
11
6


#include <stdio.h>
#define N_MAX 50

int main(void)
{
     int hand[N_MAX], wan, n, i, j;

     while(1){
	  scanf("%d %d",&n,&wan);
	  if(n+wan==0) return 0;

	  for(i=0; i<n; i++) hand[i]=0;

	  i=0;
	  while(1){
	       if(wan) wan--, hand[i]++;
	       else wan+=hand[i], hand[i]=0;

	       if(!wan){
		    for(j=0; j<n; j++) if(j!=i && hand[j]) break;
		    if(j==n) break;
	       }

	       i = (i+1)%n;
	  }

	  printf("%d\n",i);
     }

     return 0;
}

Problem A: Next Mayor

One of the oddest traditions of the town of Gameston may be that even
the town mayor of the next term is chosen according to the result of a game.
When the expiration of the term of the mayor approaches, at least
three candidates, including the mayor of the time, play a game of
pebbles, and the winner will be the next mayor.

The rule of the game of pebbles is as follows.
In what follows, n is the number of participating candidates.

Requisites

A round table, a bowl, and plenty of pebbles.

Start of the Game

A number of pebbles are put into the bowl;
the number is decided by the Administration Commission using
some secret stochastic process.
All the candidates, numbered from 0 to n-1 sit around the round table,
in a counterclockwise order. Initially, the bowl is handed to the
serving mayor at the time, who is numbered 0.

Game Steps

When a candidate is handed the bowl and if any pebbles are in it,
one pebble is taken out of the bowl and is
kept, together with those already at hand, if any.
If no pebbles are left in the bowl, the candidate puts
all the kept pebbles, if any, into the bowl. Then, in either case, the bowl is
handed to the next candidate to the right.

This step is repeated until the winner is decided.

End of the Game

When a candidate takes the last pebble in the bowl, and no other
candidates keep any pebbles, the game ends and that candidate with all
the pebbles is the winner.

A math teacher of Gameston High, through his analysis, concluded that this game will always end within a finite number of steps, although the number of required steps can be very large.

Input

The input is a sequence of datasets. Each dataset is a line
containing two integers n and p separated by a single
space. The integer n is the number of the candidates including
the current mayor, and the integer p is the total number of the
pebbles initially put in the bowl. You may assume 3 ≤ n ≤ 50
and 2 ≤ p ≤ 50.

With the settings given in the input datasets, the game will end within 1000000 (one million) steps.

The end of the input is indicated by a line
containing two zeros separated by a single space.

Output

The output should be composed of lines corresponding to input datasets
in the same order, each line of which containing the candidate number
of the winner.
No other characters should appear in the output.

Sample Input

3 2
3 3
3 50
10 29
31 32
50 2
50 50
0 0

Output for the Sample Input

1
0
1
5
30
1
13


Bridge Removal

ICPC islands once had been a popular tourist destination.
For nature preservation, however, the government decided to prohibit entrance to the islands,
and to remove all the man-made structures there.
The hardest part of the project is to remove all the bridges connecting the islands.

There are n islands and n-1 bridges.
The bridges are built so that all the islands are reachable from all the other islands by
crossing one or more bridges.
The bridge removal team can choose any island as the starting point, and can repeat either of the
following steps.

Move to another island by crossing a bridge that is connected to the current island.

Remove one bridge that is connected to the current island, and stay at the same island after the removal.

Of course, a bridge, once removed, cannot be crossed in either direction.
Crossing or removing a bridge both takes time proportional to the length of the bridge.
Your task is to compute the shortest time necessary for removing all the bridges.
Note that the island where the team starts can differ from where the team finishes the work.

Input

The input consists of at most 100 datasets.
Each dataset is formatted as follows.

n

p2 p3 ... pn

d2 d3 ... dn

The first integer n (3 ≤ n ≤ 800) is the number of the islands.
The islands are numbered from 1 to n.
The second line contains n-1 island numbers pi
(1 ≤ pi < i), and tells that for each i
from 2 to n the island i and the island pi are connected by a bridge.
The third line contains n-1 integers di (1 ≤ di ≤ 100,000)
each denoting the length of the corresponding bridge.
That is, the length of the bridge connecting the island i and pi
is di. It takes di units of time to cross the bridge, and
also the same units of time to remove it.

Note that, with this input format, it is assured that all the islands are reachable each other by
crossing one or more bridges.

The input ends with a line with a single zero.

Output

For each dataset, print the minimum time units required to remove all the bridges in a single line.
Each line should not have any character other than this number.

Sample Input

4
1 2 3
10 20 30
10
1 2 2 1 5 5 1 8 8
10 1 1 20 1 1 30 1 1
3
1 1
1 1
0

Output for the Sample Input

80
136
2


#include<stdio.h>
#include<string.h>
#define min(a,b)(a)<(b)?(a):(b)
#define  MAX_N (1<<18)
#define INF 10000001
int N;
int num[MAX_N];
int tree[2*MAX_N-1];

void init(int _n)
{
	int i;
	for(N=1;N<=_n;N*=2);
	for(i=0;i<2*N-1;i++)
		tree[i]=INF;
}

void update(int p,int a)
{
	p+=N-1;
	tree[p]=a;
	while(p>0)
	{
		p=(p-1)/2;
		tree[p]=min(tree[2*p+1],tree[2*p+2]);
	}
}

int query(int a,int b,int k,int l,int r)
{
	if(r<=a||b<=l)
		return INF;
	if(a<=l&&r<=b)
		return tree[k];
	else
	{
		int t1=query(a,b,2*k+1,l,(l+r)/2);
		int t2=query(a,b,2*k+2,(l+r)/2,r);
		return min(t1,t2);
	}
}

int main()
{
	int n,i,t,q,x,y,z;
	scanf("%d%d",&n,&q);
	init(n);
	for(i=0;i<n;scanf("%d",&t),num[i++]=t);
	for(;q--;)
	{
		scanf("%d%d%d",&x,&y,&z);
		switch(x)
		{
		case 0:t=num[z];memmove(num+y+1,num+y,(z-y)*4);num[y]=t;;break;
		case 1:for(i=0;i<n;update(i,num[i]),i++);printf("%d\n",query(y,z+1,0,0,N));break;
		case 2:num[y]=z;break;
		}
	}
	return 0;
}

Problem I : RMQ

n 個の数字a0 ,a1 , ... ,an-1 とq が与えられる。

q 個のクエリーに対して適切な処理を行なって欲しい。

クエリーは以下の3種類の操作が存在する。

値のシフトを行う

l とr のペアが与えられる。(l < r )
al から ar までの値を Circular Shiftさせる。

0 1 2 3 4 5 6 7 8 9

に対してl=2,r=5というクエリーが与えられたとする。

シフトを行った数字列は

0 1 5 2 3 4 6 7 8 9

となる。

最小値を求める

l とr のペアが与えられる。(l ≤ r )

al から arまでの値の中で最小の値を求める。

値の更新

pos と val のペアが与えられる。
apos の値を val に更新する。

Input

入力は以下のフォーマットで与えられる。

n q
a0
a1
.
.
.
an-1
x1 y1 z1
x2 y2 z2
.
.
.
xq yq zq

xi = 0 なら、シフトのクエリーを表す。このとき、l = yi , r = zi とする。

xi = 1 なら、最小値を求めるクエリーを表す。このとき、l = yi , r = zi とする。

xi = 2 なら、値を更新するクエリーを表す。このとき、pos = yi , val = zi とする。

入力は以下の制約を満たす

1 ≤ n , q ≤ 200,000

0 ≤ ai ≤ 10,000,000

値を更新するクエリーについて、0 ≤ val ≤ 10,000,000

Output

クエリーとしてxi = 1 が与えられたときに、答えの値を１行に出力せよ。

Sample Input 1

10 3
0
1
2
3
4
5
6
7
8
9
1 5 7
0 2 5
1 5 7

Sample Output 1

5
4

Sample Input 2

10 10
289383
930886
692777
636915
747793
238335
885386
760492
516649
641421
2 7 368690
1 3 6
0 2 6
1 1 8
0 2 9
2 2 665123
1 5 9
0 2 8
2 7 961393
1 1 2

Sample Output 2

238335
238335
238335
368690


// AOJ 1519: Room of Time and Spirit
// 2017.12.3 bal4u@uu

#include <stdio.h>
#include <string.h>

// <????????????Union Find>
#define MAX 100003

int power[MAX];
int par[MAX], ws[MAX];

int find(int x)
{
	int p;
	if (par[x] < 0) return x;
    p = find(par[x]), ws[x] += ws[par[x]];
    return par[x] = p;
}

int weight(int x)
{
    find(x);
    return ws[x];
}

int unite(int x, int y, int w)  // x <-(w)- y (x + w = y)
{
	int tmp;

//  w += weight(x), w -= weight(y);
    w += power[x] + weight(x), w -= power[y] + weight(y);
    x = find(x), y = find(y);
    if (x == y) return 0;
    if (par[y] < par[x]) // ???????????????????????????????????????????????????.
        tmp = x, x = y, y = tmp, w = -w;

    par[x] += par[y], par[y] = x;
    ws[y] = w;
    return 1;
}

int same(int x, int y)
{
	return find(x) == find(y);
}

// *ans = x - y. ?????????????????? return 0.
int diff(int *ans, int x, int y)
{
    if (find(x) != find(y)) return 0;
	*ans = ws[x] - ws[y];
	return 1;
}
// </????????????Union Find>

char buf[40], *p;
int getint()
{
	int n = 0;
	while (*p >= '0') n = (n<<3) + (n<<1) + (*p++ & 0xf);
	p++;
	return n;
}

int main()
{
	int n, q, a, b, c;

	fgets(p=buf, 40, stdin);
	n = getint(), q = getint();
	memset(par, 0xff, (n+1)*sizeof(int));

	while (q--) {
		fgets(p=buf, 40, stdin);
		if (*p == 'I') {
			p += 3, a = getint(), b = getint(), c = getint();
			power[a] += c, power[b] += c;
			unite(a, b, c);
		} else {
			p += 8, a = getint(), b = getint();
			if (find(a) != find(b)) puts("WARNING");
			else printf("%d\n", (power[b]+ws[b]) - (power[a]+ws[a]));
		}
	}
	return 0;
}

Problem D: Room of Time and Spirit

Problem

　20XX年、とある科学者がバイオテクノロジーによって強力な人造人間を開発してしまった。この人造人間はコンピュータにより、戦闘の達人たちの細胞を組み合わせて作られているため非常に強力である。

　このままでは地球は人造人間に支配されてしまうので、 N 人の戦士たちは人造人間と戦うことにした。しかし今の戦士たちでは到底人造人間に敵わないため、修行をしなければならない。また、N 人の戦士たちはそれぞれ 1 ~ N の番号が付いている。

　この時代、天空都市AIZUには SRLU室と呼ばれる修行のための特殊な部屋が存在した。この部屋での1年は外界の時間の1日と同じであるため、短期間で戦闘力を大幅に上昇することが出来る。同時に部屋に入れる人数の上限は2人である。また、その2人が部屋に入った時、それぞれ戦闘力が上昇する。

　戦士たちは残された時間でどのように部屋に入るか検討するため、あなたに以下のクエリを処理するプログラムの作成を依頼した。

　与えられるクエリは以下の通りである。

　また以下の説明で出てくる A, B はそれぞれ戦士の番号を表す。A と B が等しい事は無い。

IN A B C

　A と B が部屋に入り、それぞれ C だけ戦闘力が上昇する。この時、(部屋に入る直前の B の戦闘力) - (部屋に入る直前の A の戦闘力) = C が成り立つ。また、この時 B の戦闘力は A の戦闘力より高い事が保証される。

COMPARE A B

　A と B の戦闘力の差 (現在の B の戦闘力) - (現在の A の戦闘力)を出力する。もしその差が特定出来なければ、WARNING と出力せよ。

Input

N Q
query1
.
.
.
queryQ

最初に戦士の人数 N , クエリの数 Q が与えられる。

次に Q 回だけクエリが与えられる。

Constraints

入力は以下の条件を満たす。

2 ≤ N ≤ 100000

1 ≤ Q ≤ 100000

1 ≤ A, B ≤ N

1 ≤ C ≤ 5000

Output

上記のように与えられたクエリを順番に処理していき、 COMPAREの入力が与えられた際に出力を行う。

Sample Input1

3 5
COMPARE 1 2
IN 1 2 5
IN 2 3 3
COMPARE 2 3
COMPARE 1 3

Sample Output1

WARNING
3
11

Sample Input2

4 3
IN 1 4 10
IN 2 3 20
COMPARE 1 2

Sample Output2

WARNING

Sample Input3

3 4
IN 2 1 2
IN 3 1 2
COMPARE 1 3
COMPARE 2 3

Sample Output3

-2
2

Sample Input4

10 4
IN 10 8 2328
IN 8 4 3765
IN 3 8 574
COMPARE 4 8

Sample Output4

-3191

Sample Input5

3 5
IN 1 2 5
IN 1 2 5
IN 2 3 10
COMPARE 1 2
COMPARE 2 3

Sample Output5

15
10


/*
AizuOnline A2011
Gather the Maps!
*/
#include <stdio.h>

int sked[50][30];
int ok_days[50];
int flag[50];
int N;

void init()
{
  int i,j;
  for(i=0;i<50;i++)
    {
      ok_days[i]=0;
      flag[i]=0;
      for(j=0;j<30;j++)
	sked[i][j]=0;
    }
}
print()
{
  int i,j;

  for(i=0;i<N;i++)
    {
      printf("%d ",ok_days[i]);
      for(j=0;j<ok_days[i];j++)
	printf("%d ",sked[i][j]);
      printf("(%d)",flag[i]);
      printf("\n");
    }
}

void update_meet(int md,int nd)
{
  int i;

  for(i=0;i<N;i++)
    if(flag[i]==md)
      flag[i]=nd;
}

void can_meet(int d1)
{
  int i,j;
  //printf("CM:%d %d \n",d,d1);

  for(i=0;i<N;i++)
    for(j=0;j<ok_days[i];j++)
      if(sked[i][j] == d1)
	{
	  if(flag[i] == 0)
	    flag[i] = d1;
	  else if(flag[i] < d1)
	    update_meet(flag[i],d1);
	}
}

int all_meet(int d)
{
  int i;
  for(i=0;i<N;i++)
    if(flag[i]!=d)
      return(0);
  return(1);
}
main()
{
  int i,j,d;
  while(EOF != scanf("%d",&N) && N)
    {
      init();
      for(i=0;i<N;i++)
	{
	  scanf("%d",&(ok_days[i]));
	  for(j=0;j<ok_days[i];j++)
	    scanf("%d",&(sked[i][j]));
	}
      if(N==1)
	{
	  printf("%d\n",1);
	  continue;
	}
      for(d=1;d<=30;d++)
	{
	  can_meet(d);
	  //print();
	  if(all_meet(d))
	    { // printf("ALL MEET\n");
	      printf("%d\n",d);
	      //fflush(stdout);
	      goto NEXT;
	    }
	}
      printf("%d\n",-1);
    NEXT: ;
    }
return(0);
}

Problem F: Gather the Maps!

はるか昔、八尾氏が残したとされる伝説の秘宝が八王子のどこかに眠っているという。 その在処を示すとされる宝の地図は、いくつかの断片に分割された状態で、八尾氏の n 人の子孫達によって受け継がれている。

今、八尾氏の子孫達は協力してその秘宝を手に入れようとしていた。 ところが、秘宝の在処を指し示す宝の地図の一部分だけでは秘宝を見つけることができない。 そこで、八尾氏の子孫達は全員で集まって地図を 1 ヶ所に集めようとした。
ところが、いざ実行に移そうとしてもなかなか予定が合わずに集まることができない。 しかしこの秘宝に関する情報は、一族において秘密裏に伝えられてきた貴重な情報である。 漏洩の危険性を考慮すると、公共の通信手段を用いて地図をやりとりすることなど問題外である。

そこで、子孫同士が直接会って地図を手渡すということを繰り返すことで、ある 1 人の子孫のところに地図を集めることにした。
なお、1 人が 1 日に会える人数に制限はないが、互いにスケジュールが空いていることが必要である。

あなたの仕事は、それぞれの子孫に対するスケジュールの空いている日のリストから、地図を集めるには最低で何日必要かを求めるプログラムを書くことである。

ちなみに、八尾氏一族の結束は非常に固い。 最終的に地図全体を手にした子孫が、他の子孫を裏切って秘宝を持ち逃げすれば、一族から制裁を受けることになる。その制裁はきわめて恐ろしいものであるため、実際にその子孫が秘宝を持ち逃げすることは事実上不可能である。

Input

入力は複数のデータセットからなる。

それぞれのデータセットは複数の行からなる。 その最初の行には、地図の断片を持った者の人数を表す整数 n (1 < n <= 50) が記述されている。 続く n 行には、それぞれの子孫のスケジュールが書かれている。
i 行目は i 人目の子孫のスケジュールが表しており、いくつかの整数が 1 文字のスペースを区切りとして書かれている。
最初の整数 fi (0 <= fi <= 30) は、その子孫のスケジュールが空いている日の日数を表す整数である。 続く fi 個の整数は、スケジュールが空いている日付を表す。 これらの日付は互いに異なり、全て 1 以上 30 以下である。

入力の最後に 0 のみを含んだ 1 行がある。

Output

各データセットに対して、1 つの整数を 1 行に出力せよ。
もし、30 日以内に地図を集めることができる場合は、地図を集めるのに最低限必要となる日数を、集めることができない場合は -1 を出力せよ。

追記 :
上記の「地図を集めるのに最低限必要となる日数」は 1 日を起点として最も早く全ての地図が集まる日付を意味する．

Sample Input

4
1 1
2 2 3
2 1 2
3 3 4 5
0

Output for the Sample Input

3


#include<stdio.h>
#include<string.h>
unsigned long long m,a;
int main(){
  int i,j,n,min,d[50]={0};
  char s[50],c[]={"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
  while(scanf("%d %s",&n,s),n){
    j=n;
    m=0;
    for(i=0;i<40;i++)d[i]=0;
    min=1000000000;
    for(i=2;i<=j;i++){
      while(j%i==0){
	j/=i;
	d[i]++;
      }
    }//printf("a\n");
    //for(i=0;i<n;i++)printf("%d %d\n",i,d[i]);
    for(i=0;s[i];i++){
      m*=n;
      for(j=0;c[j]-s[i];j++);
      m+=j;
    }//printf("%d\n",m);
    for(i=0;i<=n;i++){
      if(d[i]==0)continue;
      a=0;
      for(j=i;j<=m;j*=i)a+=m/j;
      a/=d[i];//printf("%d %lld\n",i,a);
      if(min>a)min=a;
    }

  printf("%lld\n",a);
  }
  return 0;
}

Problem C: !

You are one of ICPC participants and in charge of developing a library for multiprecision numbers
and radix conversion. You have just finished writing the code, so next you have to test if it
works correctly. You decided to write a simple, well-known factorial function for this purpose:

Your task is to write a program that shows the number of trailing zeros when you compute M!
in base N, given N and M.

Input

The input contains multiple data sets. Each data set is described by one line in the format
below:

N M

where N is a decimal number between 8 and 36 inclusive, and M is given in the string repre-
sentation in base N. Exactly one white space character appears between them.

The string representation of M contains up to 12 characters in base N. In case N is greater
than 10, capital letters A, B, C, ... may appear in the string representation, and they represent
10, 11, 12, ..., respectively.

The input is terminated by a line containing two zeros. You should not process this line.

Output

For each data set, output a line containing a decimal integer, which is equal to the number of
trailing zeros in the string representation of M! in base N.

Sample Input

10 500
16 A
0 0

Output for the Sample Input

124
2


Problem A: Strange String Manipulation

A linear congruential generator produces a series R(⋅) of pseudo-random numbers by the following for-
mulas:

where S, A, C, and M are all parameters. In this problem, 0 ≤ S, A, C ≤ 15 and M = 256.

Now suppose we have some input string I(⋅), where each character in the string is an integer between 0
and (M - 1). Then, using the pseudo-random number series R(⋅), we obtain another string O(⋅) as the
output by the following formula:

Your task is to write a program that shows the parameters S, A, and C such that the information entropy of the output string O(⋅) is minimized. Here, the information entropy H is given by the following formula:

where N is the length of the string and #(x) is the number of occurences of the alphabet x.

Input

The input consists of multiple datasets. Each dataset has the following format:

N

I(1) I(2) ... I(N)

N does not exceed 256.

The last dataset is followed by a line containing one zero. This line is not a part of any dataset and should not be processed.

Output

For each dataset, print in a line the values of the three parameters S, A, and C separated by a single space. If more than one solution gives the same minimum entropy, choose the solution with the smallest S, A, and then C.

Sample Input

5
5 4 3 2 1
5
7 7 7 7 7
10
186 8 42 24 154 40 10 56 122 72
0

Output for the Sample Input

0 1 1
0 0 0
8 7 14


#include <stdio.h>
#include <string.h>

int dp[80001][11];//[i][mod]
int ans[11];
int main() {
	char str[80001];
	while (1) {
		for (int i = 0; i < 80001; i++) {
			for (int j = 0; j < 11; j++) {
				dp[i][j] = 0;
			}
		}
		for (int i = 0; i < 11; i++) {
			ans[i] = 0;
		}
		scanf("%s", str);
		if (strcmp(str, "0")==0)break;
		int length = strlen(str);
		dp[1][str[0] - '0']++;
		for (int i = 2; i <= length; i++) {
			int digit = str[i - 1] - '0';
			for (int mod = 0; mod <= 10; mod++) {
				dp[i][((mod * 10) + digit) % 11] = dp[i - 1][mod];
			}
			if(digit!=0)dp[i][digit]++;

			for (int mod = 0; mod <= 10; mod++) {
				ans[mod] += dp[i][mod];
			}
		}
		printf("%d\n", ans[0]);
	}
	return 0;
}

Problem H: Eleven Lover

Edward Leven loves multiples of eleven very much. When he sees a number, he always tries
to find consecutive subsequences (or substrings) forming multiples of eleven. He calls such
subsequences as 11-sequences. For example, he can find an 11-sequence 781 in a number 17819.

He thinks a number which has many 11-sequences is a good number. He would like to find out
a very good number. As the first step, he wants an easy way to count how many 11-sequences
are there in a given number. Even for him, counting them from a big number is not easy.
Fortunately, one of his friends, you, is a brilliant programmer. He asks you to write a program
to count the number of 11-sequences. Note that an 11-sequence must be a positive number
without leading zeros.

Input

The input is a sequence of lines each of which contains a number consisting of less than or equal
to 80000 digits.

The end of the input is indicated by a line containing a single zero, which should not be processed.

Output

For each input number, output a line containing the number of 11-sequences.

You can assume the answer fits in a 32-bit signed integer.

Sample Input

17819
1111
11011
1234567891011121314151617181920
0

Output for the Sample Input

1
4
4
38


#include <stdio.h>
int disabled_route[16][16];

int main(void){
	int dataset;
	scanf("%d", &dataset);

	while(dataset--){
		int gx, gy, matatabi;
		int x1, y1, x2, y2;
		int foo;
		for(x1=0;x1<16;x1++)
		for(y1=0;y1<16;y1++)
		disabled_route[x1][y1] = 0;

		scanf("%d", &gx);
		scanf("%d", &gy);
		scanf("%d", &matatabi);

		while(matatabi--){
			scanf("%d", &x1);
			scanf("%d", &y1);
			scanf("%d", &x2);
			scanf("%d", &y2);
			if(x1 > x2) {
				foo = x1;
				x1 = x2;
				x2 = foo;
			}else if(y1 >y2) {
				foo = y1;
				y1 = y2;
				y2 = foo;
			}
			disabled_route[x2][y2] += ( x1==x2 ? 1 : 2 );
		}

		if(foo = count(gx, gy)) printf("%d\n", foo);
		else printf("Miserable Hokusai!\n");
	}

	return 0;
}

int count(x, y){
	if(x==0 && y==0) return 1;
	switch(disabled_route[x][y]){
	  case 3:
		return 0;
	  case 2:
		return y ? count(x, y-1) : 0;
	  case 1:
		return x ? count(x-1, y) : 0;
	  case 0:
		return (y ? count(x, y-1) : 0) + (x ? count(x-1, y) : 0);
	}
}

/* note
1	vertical
2	horizontal
*/

Problem B: 平安京ウォーキング

平安京は、道が格子状になっている町として知られている。

平安京に住んでいるねこのホクサイは、パトロールのために毎日自宅から町はずれの秘密の場所まで行かなければならない。しかし、毎日同じ道を通るのは飽きるし、後を付けられる危険もあるので、ホクサイはできるだけ毎日異なる経路を使いたい。その一方で、ホクサイは面倒臭がりなので、目的地から遠ざかるような道は通りたくない。

平安京のあちこちの道にはマタタビが落ちていて、ホクサイはマタタビが落ちている道を通ることができない。そのような道を通るとめろめろになってしまうからである。幸いなことに、交差点にはマタタビは落ちていない。

ホクサイは、自宅から秘密の場所までの可能な経路の数を知りたい。ここで、ホクサイの自宅は (0, 0) にあり、秘密の場所は(gx, gy)にある。道は x = i (i は整数), y = j (j は整数) に格子状に敷かれている。

Input

入力の1行目には、秘密の場所の座標 (gx, gy) が与えられる。これらはいずれも1以上15以下の整数で、空白1個で区切られて与えられる。 2行目にはマタタビが落ちている区間の数 p (0 ≤ p ≤ 100) が与えられ、続くp行にはマタタビが落ちている区間が1行に1区間ずつ与えられる。 p個の区間は互いに異なる。 1区間は x1 y1 x2 y2 の形で表され、(x1, y1) と (x2, y2) を端点とする、x軸またはy軸に平行な長さ1の線分である。 x1, x2 は [0, gx] の範囲にあり、y1, y2 は [0, gy] の範囲にある。

Output

可能な経路の数を出力せよ。可能な経路が1つもない場合は "Miserable Hokusai!" と1行に出力せよ。

Notes on Submission

上記形式で複数のデータセットが与えられます。入力データの 1 行目にデータセットの数が与えられます。各データセットに対する出力を上記形式で順番に出力するプログラムを作成して下さい。

Sample Input

4
2 2
0
1 1
2
0 0 0 1
0 0 1 0
4 3
4
1 0 0 0
3 3 4 3
4 1 4 0
0 2 0 3
15 15
0

Output for the Sample Input

6
Miserable Hokusai!
5
155117520


Problem D: Mr. Rito Post Office

あなたは離島の郵便局に勤めるプログラマである．あなたの住んでいる地域は，複数の島々からなる．各島には一つ以上の港町がある．それらに加えて他の町や村があるかもしない．ある島から別の島に向かうためには船を使わなければならない．一つの島の中を回るには陸路が使えるが，海路を利用した方が速いこともある．

近年行われた郵便局の民営化をきっかけに，経費削減に向けて郵便配達員の人員整理が全国的に行われた．離島の郵便局もその例外ではなく，結果として郵便配達員は利藤さんただ一人となってしまった．その郵便局が集配を担当する地域は非常に広いため，一人で集配するのは大変な作業である．なので，どのようにすれば効率的に集配を行えるのか，利藤さんがあなたに助けを求めてきた．

あなたの仕事は，利藤さんがたどるべき町や村の集配順序が与えられたときに，最短巡回経路を求めるプログラムを書くことである．

利藤さんは，決して指定された順序以外で集配業務を行うことができない．しかし，ある町や村から別の町や村へ移動する際に，他の町や村を経由して移動することは許可されている．また，利藤さんは島々を巡るための一隻の船を持っている．

例えば，町A，町B，村Cという集配順序が与えられた場合，町Aから町Bへ向かう際にどの町や村を経由してもかまわない．このとき，村Cを経由しても構わないが，集配順序を守るためには，一度町Bに行って集配をおこなってから，改めて村Cを訪れて集配をおこなわなければならない．また，町Aから海路を用いて町Bに向かい，町Bから陸路を用いて村Cに向かった場合，船を町Bに置いたままになる．したがって，次に海路を使いたい場合は町Bに戻る必要がある．

一つの町や村において複数回集配をしなければならない場合もある．たとえば，町A，村B，町C，村Bという集配順序が与えられるかもしれない．このとき，町Aから村Bをたどらずに町Cに向かった場合は，町Cでいきなり集配をおこなうことはできない．最初の村Bでの集配が終わっていないからである．町Cで集配を済ませた後で村Bを訪れて集配しても，一回目の村Bの集配を終わらせたことにはならない．

利藤さんは，はじめに必ずある港町に船とともにいる．利藤さんはベテランであるため，移動時間以外の集配作業にかかる時間は無視してよい．また，最後の町または村での集配業務が完了するまでの時間だけが問題であり，船をもとの位置に戻して郵便局に帰るまでの時間は考慮しなくてよい．

Input

入力は複数のデータセットから構成される．各データセットの形式は次に示すとおりである．

N M

x1 y1 t1 sl1

x2 y2 t2 sl2

...

xM yM tM slM

R

z1 z2 ... zR

データセットの中の入力項目は，すべて非負の整数である．行中の入力項目の区切りは空白 1 個である．

最初の行は，陸路及び海路網の大きさを規定する．

N (2 ≤ N ≤ 200) は，町または村の数である．
それぞれの町または村には，1 から N までの固有の番号を割り当てる．
M (1 ≤ M ≤ 10000) は，陸路と海路の合計本数である．

2 行目から 1 + M 行目は，陸路または海路の記述である．
xi と yi (1 ≤ xi, yi ≤ N) は両端の町または村の番号を表す．
ti (1 ≤ ti ≤ 1000) はその陸路または海路の移動時間を表す．
sli は ‘L’ または ‘S’ のいずれかであり，Lは陸路を，Sは海路をそれぞれ表す．

ある2つの町や村を直接結ぶ陸路または海路が2本以上存在することがある． それぞれの陸路または海路は双方向であり，すなわちどちらの向きにも移動できる．

M + 2 行目の R (1 ≤ R ≤
1000)は，利藤さんが担当する集配先の数を表す． M + 3 行目には，集配先の町や村の番号 zi (1 ≤ zi ≤ N) が集配順に R 個並んでいる．

初期状態では利藤さんと船はともに港町 z1 に存在する． 初期状態から集配先の町や村へは，必ず何らかの方法で移動することができる．

入力の終わりは，空白で区切られた2つの0を含む1行で示される．

Output

入力の各データセットに対して，与えられた集配順序で利藤さんが町と村を巡回するために必要な最短移動時間を求め，1行に出力せよ．

Sample Input

3 3
1 2 5 L
1 2 7 S
2 3 11 S
3
1 2 3
5 5
1 2 15 L
2 3 10 L
4 5 7 L
1 3 30 S
3 4 100 S
5
1 3 5 4 1
0 0

Output for the Sample Input

18
269


// AOJ 2457 Adhoc Translation
// 2018.3.6 bal4u

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define QMAX 10005
typedef struct { int t, s; } QUE;
QUE que[QMAX]; int qsize;

#define PARENT(i) ((i)>>1)
#define LEFT(i)   ((i)<<1)
#define RIGHT(i)  (((i)<<1)+1)

void min_heapify(int i)
{
	int l, r, min;
	QUE qt;

	l = LEFT(i), r = RIGHT(i);
	if (l < qsize && que[l].t < que[i].t) min = l; else min = i;
	if (r < qsize && que[r].t < que[min].t) min = r;
	if (min != i) {
		qt = que[i], que[i] = que[min], que[min] = qt;
		min_heapify(min);
	}
}

void deq()
{
	que[0] = que[--qsize];
	min_heapify(0);
}

void enq(int s, int t)
{
	int i, min;
	QUE qt;

	i = qsize++;
	que[i].s = s, que[i].t = t;
	while (i > 0 && que[min = PARENT(i)].t > que[i].t) {
		qt = que[i], que[i] = que[min], que[min] = qt;
		i = min;
	}
}

#define INF 0x01010101
#define MAX 805
typedef struct { int to, rev; int cap, cost; } E;
E *edge[MAX]; int hi[MAX], lim[MAX];
int V;				// 頂点数
int potential[MAX], min_cost[MAX], prevv[MAX], preve[MAX];

void check_lim(int a)
{
	if (hi[a] < lim[a]) return;
	if (lim[a] == 0) {
		lim[a] = 4, hi[a] = 0;
		edge[a] = malloc(sizeof(E) *lim[a]);
	} else if (hi[a] == lim[a]) {
		int k = lim[a];
		if (k > 256) k = 256;
		lim[a] += k;
		edge[a] = realloc(edge[a], sizeof(E) *lim[a]);
	}
}

void add_edge(int from, int to, int cap, int cost)
{
	int f, t;
	E *ep;

	check_lim(from), check_lim(to);
	f = hi[from]++, t = hi[to]++;
	ep = &edge[from][f], ep->to = to, ep->cap = cap, ep->cost = cost, ep->rev = t;
	ep = &edge[to][t], ep->to = from, ep->cap = 0, ep->cost = -cost, ep->rev = f;
}

int minCostFlow(int S, int T, int F)
{
	int i, s, ns, t, nt, ret;
	E *ep;

	ret = 0;
//	memset(potential, 0, V << 2);

    while (F > 0) {
		memset(min_cost, INF, V << 2);
		qsize = 0;
		enq(S, 0), min_cost[S] = 0;

		while (qsize) {
			s = que[0].s, t = que[0].t, deq();
			if (min_cost[s] < t) continue;

			for (i = 0; i < hi[s]; i++) {
				ep = &edge[s][i], ns = ep->to;
				nt = t + ep->cost + potential[s] - potential[ns];
				if(ep->cap > 0 && min_cost[ns] > nt) {
					min_cost[ns] = nt;
					prevv[ns] = s, preve[ns] = i;
					enq(ns, nt);
				}
			}
		}
		if (min_cost[T] == INF) return -1;
		for (s = 0; s < V; s++) potential[s] += min_cost[s];

		t = F;
		for (s = T; s != S; s = prevv[s]) {
			ep = &edge[prevv[s]][preve[s]];
			if (t > ep->cap) t = ep->cap;
		}
		F -= t;

		ret += t * potential[T];
		for (s = T; s != S; s = prevv[s]) {
			ep = &edge[prevv[s]][preve[s]];
			ep->cap -= t;
			edge[s][ep->rev].cap += t;
		}
	}
	return ret;
}

typedef struct { int c, w; char *s; } S;	// w:len, c:cnt
S web[50000]; int sz;
S dic[402];
char buf[102][1005];
char word[402][25];
char dp0[22][22], dp[22][22];

int string_distance(char *s1, int w1, char *s2, int w2)
{
	int  i, j, d, min;

	memcpy(dp, dp0, sizeof(dp));
	for (j = 1; j <= w1; j++) for (i = 1; i <= w2; i++) {
		d = (s1[j-1] != s2[i-1]);
		min =     dp[j-1][i  ] + 1;
		if (min > dp[j  ][i-1] + 1) min = dp[j  ][i-1] + 1;
		if (min > dp[j-1][i-1] + d) min = dp[j-1][i-1] + d;
		dp[j][i] = min;
	}
	return dp[w1][w2];
}

int cmp(S *a, S *b) { return strcmp(a->s, b->s); }

int uniq(S *a, int n)
{
	int i, j, k;

	for (i = 0, j = 1; j < n; j++) {
		k = j; while (j < n && a[i].w == a[j].w && !memcmp(a[i].s, a[j].s, a[i].w)) j++;
		a[i].c = j-k+1; if (j < n) if (++i != j) a[i] = a[j];
	}
	return i+1;
}

int main()
{
	int N, M, i, j, source, sink;
	char b[20], *p, *q;

	i = 21; while (i--) dp0[i][0] = i;
	i = 21; while (i--) dp0[0][i] = i;

	fgets(b, 20, stdin), sscanf(b, "%d%d", &N, &M);
	sz = 0; for (i = 0; i < N; i++) {
		fgets(p=buf[i], 1002, stdin);
		while (1) {
			q = p; while (*p > ' ') p++;
			web[sz].c = 1, web[sz].s = q, web[sz++].w = p-q;
			if (*p < ' ') { *p = 0; break; }
			*p++ = 0;
		}
	}
	qsort(web, sz, sizeof(S), cmp), sz = uniq(web, sz);

	for (i = 0; i < M; i++) {
		fgets(p=word[i], 22, stdin);
		q = p; while (*p > ' ') p++; *p = 0;
		dic[i].s = q, dic[i].w = p-q;
	}

	source = sz + M, sink = source + 1, V = sink + 1;

	for (i = 0; i < sz; i++) add_edge(source, i, 1, 0);
	for (i = 0; i < sz; i++) for (j = 0; j < M; j++) {
		add_edge(i, sz+j, 1, web[i].c*string_distance(web[i].s, web[i].w, dic[j].s, dic[j].w));
	}
	for (j = 0; j < M; j++) add_edge(sz+j, sink, 1, 0);

	printf("%d\n", minCostFlow(source, sink, sz));
	return 0;
}

Problem A: Adhoc Translation

One day, during daily web surfing, you encountered a web page which was written in a language you've never seen. The character set of the language was the same as your native language; moreover, the grammar and words seemed almost the same. Excitedly, you started to "decipher" the web page. The first approach you tried was to guess the meaning of each word by selecting a similar word from a dictionary of your native language. The closer two words (although from the different languages) are, the more similar meaning they will have.

You decided to adopt edit distance for the measurement of similarity between two words. The edit distance between two character sequences is defined as the minimum number of insertions, deletions and substitutions required to morph one sequence into the other. For example, the pair of "point" and "spoon" has the edit distance of 3: the latter can be obtained from the former by deleting 't', substituting 'i' to 'o', and finally inserting 's' at the beginning.

You wanted to assign a word in your language to each word in the web text so that the entire assignment has the minimum edit distance. The edit distance of an assignment is calculated as the total sum of edit distances between each word in the text and its counterpart in your language. Words appearing more than once in the text should be counted by the number of appearances.

The translation must be consistent across the entire text; you may not match different words from your dictionary for different occurrences of any word in the text. Similarly, different words in the text should not have the same meaning in your language.

Suppose the web page says "qwerty asdf zxcv" and your dictionary contains the words "qwert", "asf", "tyui", "zxcvb" and "ghjk". In this case, you can match the words in the page as follows, and the edit distance of this translation is 3: "qwert" for "qwerty", "asf" for "asdf" and "zxcvb" for "zxcv".

Write a program to calculate the minimum possible edit distance among all translations, for given a web page text and a word set in the dictionary.

Input

The first line of the input contains two integers N and M.

The following N lines represent the text from the web page you've found. This text contains only lowercase alphabets and white spaces. Then M lines, each containing a word, describe the dictionary to use. Every word consists of lowercase alphabets only, and does not contain more than 20 characters.

It is guaranteed that 1 ≤ N ≤ 100 and 1 ≤ M ≤ 400. Also it is guaranteed that the dictionary is made up of many enough words, which means the number of words in the dictionary is no less than the kinds of words in the text to translate. The length of each line in the text does not exceed 1000.

Output

Output the minimum possible edit distance in a line.

Sample Input 1

1 5
qwerty asdf zxcv
qwert
asf
tyui
zxcvb
ghjk

Output for the Sample Input 1

3


// AOJ 2751 Baseball
// 2018.2.2 bal4u

#include <stdio.h>

#define M 1000000007
#define N 4000000

int fact[N+2], inv[N+2], factinv[N+2];

//#define getchar_unlocked()  getchar()
int in()
{
	int n = 0;
	int c = getchar_unlocked();
	do n = (n<<3)+(n<<1) + (c & 0xf), c = getchar_unlocked();
	while (c >= '0');
	return n;
}

int comb(int n, int k)
{
	if (n < 0 || k < 0) return 0;
	return (int)((long long)fact[n] * factinv[k] % M * factinv[n-k] % M);
}

int H(int n, int k)
{
	if (!n && !k) return 1;
    return comb(n+k-1, k);
}

int main()
{
	int a, b, c, sx, sy, i;
	long long ans, t;

	fact[0] = 1; for (i = 1; i <= N; i++)
		fact[i] = (long long)fact[i-1] * i % M;
	inv[1] = 1; for (i = 2; i <= N; i++)
		inv[i] = M - (M / i) * (long long)inv[M % i] % M;
	factinv[0] = 1; for (i = 1; i <= N; i++)
		factinv[i] = (long long)factinv[i-1] * inv[i] % M;

	while (1) {
		a = in(), b = in(), c = in(), sx = in(), sy = in();
		if ((a|b|c|sx|sy) == 0) break;

		ans = 0;
		for (i = a; i <= sx; i++) {
			t = H(a, i-a);
			t = t * H(b, sy-sx+i-b) % M;
			t = t * H(a+b+c, sx-i) % M;
			ans += t;
			if (ans >= M) ans -= M;
		}
		ans = ans * comb(a+b+c, a) % M;
		ans = ans * comb(b+c, b) % M;
		printf("%d\n", (int)ans);
	}
    return 0;
}

MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

野球観戦

先日，あなたの競技プログラミング仲間であるOさんは野球観戦に出かけた．
観戦した試合は，チームXとチームYの合計 4 試合の対戦だったが，一方的な展開となり，全試合でチームXが勝利した．
しかも，4 試合を通じたXの合計得点は 33 点だったのに対し，Yの合計得点はたったの 4 点だった．

あまりに一方的な内容のため，試合内容への興味が薄れてしまったOさんは，試合を観戦している間も競技プログラミングの作問ネタをついつい考えてしまっていた．
その甲斐もあって，Oさんは以下のような問題を思いついた．

野球チームXとYが対戦し，Xが勝った試合数，Yが勝った試合数，引き分けの試合数がそれぞれ A, B, C 試合だったとする．
また，全 A+B+C 試合を通じたX，Yの総得点は，それぞれ SX 点，SY 点だったとする．得点は全て 0 以上の整数である．
XとYが合計 A+B+C 試合対戦したとき，全試合の結果としてこのような条件を満たす各試合のスコアの並びは何通り有り得るだろうか？

ここで，ある試合で勝利する条件は，その試合における得点が，相手チームの得点よりも多いことであり，等しい場合は引き分けとなる．

また，各試合のスコアの並びを求める際，対戦した全試合の結果を比べた時，XとYの得点の組み合わせが同じでも，その順序が異なれば区別する必要がある．
例えば，XとYが 2 試合対戦した結果，共に 1 勝ずつし，引き分けが無く，XとYの総得点が共に 1 点ずつだったとする．
この場合，各試合におけるX，Yの得点を (Xの得点) - (Yの得点) という表記で表し，合計 2 試合の結果を並べると，以下の 2 通りが与えられた条件を満たす．

1 - 0, 0 - 1

0 - 1, 1 - 0

試合の順序を区別して数えるので，これらは区別される．

あなたにはこの答えを求めるプログラムを作って欲しい．
ただし，求める数はとても大きい数になり得るため，求める数を 1,000,000,007 で割った余りを答えるようにして欲しい．

Input

入力は複数のデータセットからなる．
各データセットは 1 行からなり，次の形式で表される．

A B C SX SY

ここで，A はチームXの勝利数，B はチームYの勝利数，C は引き分けの試合数，SX はチームXの総得点，SY はチームYの総得点を表す．
A, B, C, SX, SY は全て 0 以上 1,000,000 以下の整数であり，かつ 0 < A+B+C を満たす．

入力の終わりは，5 つのゼロからなる行で示される．

Output

各データセットについて，与えられた条件を満たす場合の数を 1,000,000,007 で割った余りのみからなる行を 1 行で出力せよ．

Sample Input

1 1 0 1 1
0 0 2 3 2
4 0 0 33 4
5 4 2 20 25
4726 87361 2742 23497 162843
328324 420923 12782 834286 538297
0 0 0 0 0

Output for Sample Input

2
0
114660
512095631
673703234
166259450


#include<stdio.h>
#include<string.h>
#define N 1001
int main()
{
  int n,i,j;
  char sum[N],num[N];
  scanf("%d",&n);
  for(i=0;i<n;i++){
    scanf("%s",sum);
    scanf("%s",num);
    printf("%d\n",xu(sum,num));
  }
  return 0;
}

int xu(char *S,char *A)
{
  int c[N][N],i,j,a,b;
  a=strlen(S)+1;
  b=strlen(A)+1;
  for(i=1;i<a;i++)c[0][i]=0;
  for(i=0;i<b;i++)c[i][0]=0;

  for(i=1;i<a;i++){
    for(j=1;j<b;j++){
      if(S[i-1]==A[j-1])c[i][j]=c[i-1][j-1]+1;
      else if(c[i-1][j]>=c[i][j-1])c[i][j]=c[i-1][j];
      else c[i][j]=c[i][j-1];
    }
  }
  return c[a-1][b-1];
}

MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Longest Common Subsequence

For given two sequences $X$ and $Y$, a sequence $Z$ is a common subsequence of $X$ and $Y$ if $Z$ is a subsequence of both $X$ and $Y$. For example, if $X = \{a,b,c,b,d,a,b\}$ and $Y = \{b,d,c,a,b,a\}$, the sequence $\{b,c,a\}$ is a common subsequence of both $X$ and $Y$. On the other hand, the sequence $\{b,c,a\}$ is not a longest common subsequence (LCS) of $X$ and $Y$, since it has length 3 and the sequence $\{b,c,b,a\}$, which is also common to both $X$ and $Y$, has length 4. The sequence $\{b,c,b,a\}$ is an LCS of $X$ and $Y$, since there is no common subsequence of length 5 or greater.

Write a program which finds the length of LCS of given two sequences $X$ and $Y$. The sequence consists of alphabetical characters.

Input

The input consists of multiple datasets. In the first line, an integer $q$ which is the number of datasets is given. In the following $2 \times q$ lines, each dataset which consists of the two sequences $X$ and $Y$ are given.

Output

For each dataset, print the length of LCS of $X$ and $Y$ in a line.

Constraints

$1 \leq q \leq 150$

$1 \leq$ length of $X$ and $Y$ $\leq 1,000$

$q \leq 20$ if the dataset includes a sequence whose length is more than 100

Sample Input 1

3
abcbdab
bdcaba
abc
abc
abc
bc

Sample Output 1

4
3
2

Reference

Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.


#include<stdio.h>
#include<string.h>

#define N (1000 + 10)
#define max(a,b)(a<b?b:a)

int dp[N][N];
char a[N],b[N];

int lcs(void)
{
  const int a_size=strlen(a)-1;
  const int b_size=strlen(b)-1;

  int i,j;

  memset(dp,0,sizeof(dp));

  for(i=1;i<a_size+1;++i)
    {
      for(j=1;j<b_size+1;++j)
	{
	  int mx =max(dp[i][j-1],dp[i-1][j]);
	  if(a[i-1]==b[j-1])
	    {
	      mx=max(mx,dp[i-1][j-1]+1);
	    }
	  dp[i][j]=mx;
	}
    }
  return dp[a_size][b_size];
}

int main()
{
  int n,i;
  scanf("%d\n",&n);

  for(i=0;i<n;i++)
    {
      fgets(a,N,stdin);
      fgets(b,N,stdin);
      printf("%d\n",lcs());
    }

  return 0;
}