算法设计与分析考前复习
qiwang的NOJ系统在考前一天崩了,强烈建议开发新OJ
另外,由于以下这些题是我上完数电实验用了下午和晚上时间写的,可能会出一些错。
分治法复习
二分查找
描述
给定一个单调递增的整数序列,问某个整数是否在序列中。
输入
第一行为一个整数n,表示序列中整数的个数;第二行为n(n不超过10000)个整数;第三行为一个整数m(m不超过50000),表示查询的个数;接下来m行每行一个整数k。
输出
每个查询的输出占一行,如果k在序列中,输出Yes,否则输出No。
输入样例
5
1 3 4 7 11
3
3
6
9
输出样例
Yes
No
No
#include <iostream>
using namespace std;
bool BinarySearch(int *a,int low,int high,int k)
{
int mid;
if(low <= high)
{
mid = (low + high) / 2;
if(a[mid] == k)
return true;
if(a[mid] > k)
return BinarySearch(a, low, mid - 1, k);
else
return BinarySearch(a, mid + 1, high, k);
}
else
return false;
}
int main()
{
int n1, n2, i;
int a[10000], k[50000];
cin >> n1;
for (i = 0; i < n1;i++)
{
cin >> a[i];
}
cin >> n2;
for (i = 0; i < n2;i++)
{
cin >> k[i];
}
for (i = 0; i < n2;i++)
{
if(BinarySearch(a,0,n1-1,k[i]))
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}
快速排序
描述
给定一个数列,用快速排序算法把它排成升序。
输入
第一行是一个整数n(n不大于10000),表示要排序的数的个数;下面一行是用空格隔开的n个整数。
输出
输出排序后的数列,每个数字占一行。
输入样例
5
3 2 1 4 5
输出样例
1
2
3
4
5
#include <iostream>
using namespace std;
void QuickSort(int *a,int low,int high)
{
int i = low, j = high;
int temp = a[low];
while(i != j)
{
while(a[j] >= temp && j > i)
j--;
a[i] = a[j];
while(a[i] <= temp && j > i)
i++;
a[j] = a[i];
}
a[i] = temp;
if(i > low)
QuickSort(a, low, i);
if(i < high)
QuickSort(a, i + 1, high);
}
int main()
{
int i, n;
int a[10000];
cin >> n;
for (i = 0; i < n;i++)
{
cin >> a[i];
}
QuickSort(a, 0, n - 1);
for (i = 0; i < n;i++)
{
cout << a[i] << endl;
}
}
循环赛日程表
#include <iostream>
#define MAX 100
using namespace std;
int k;
int a[MAX][MAX];
void Plan(int k)
{
int i, j, n, t, temp;
n = 2;
a[1][1] = 1;
a[1][2] = 2;
a[2][1] = 2;
a[2][2] = 1;
for (t = 1; t < k;t++)
{
temp = n;
n = n * 2;
for (i = temp + 1; i <= n;i++)
for (j = 1; j <= temp;j++)
a[i][j] = a[i - temp][j] + temp;
for (i = 1; i <= temp;i++)
for (j = temp + 1; j <= n; j++)
a[i][j] = a[i + temp][(j + temp) % n];
for (i = temp + 1; i <= n;i++)
for (j = temp + 1; j <= n;j++)
a[i][j] = a[i - temp][j - temp];
}
}
int main()
{
k = 3;
int n = 1 << k;
Plan(k);
for (int i = 1; i <= n;i++)
{
for (int j = 1; j <= n;j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
}
回溯法复习
穷举n位二进制数
描述
输入一个小于20的正整数n,要求按从小到大的顺序输出所有的n位二进制数,每个数占一行。
输入
输入一个小于20的正整数n。
输出
按从小到大的顺序输出所有的n位二进制数,每个数占一行。
输入样例
3
输出样例
000
001
010
011
100
101
110
111
#include <iostream>
using namespace std;
int a[20];
int n;
void display()
{
int i;
for (i = 0; i < n;i++)
{
cout << a[i];
}
cout << endl;
}
void dfs(int i)
{
int j;
if(i == n)
{
display();
}
else{
for (j = 0; j <= 1;j++)
{
a[i] = j;
dfs(i + 1);
a[i] = 0;
}
}
}
int main()
{
cin >> n;
dfs(0);
}
走迷宫
#include <iostream>
using namespace std;
int m, n;
int flag;
int maze[100][100];
bool check(int x,int y)
{
if(maze[x][y] == 0 && x >= 0 && x < m && y >= 0 && y < n)
{
return true;
}
else
return false;
}
void dfs(int start_x,int start_y,int end_x,int end_y)
{
if(start_x == end_x && start_y == end_y)
{
flag = 1;
return;
}
else{
maze[start_x][start_y] = 1;
if(check(start_x+1,start_y))
dfs(start_x + 1, start_y, end_x, end_y);
if(check(start_x,start_y+1))
dfs(start_x, start_y + 1, end_x, end_y);
if(check(start_x-1,start_y))
dfs(start_x - 1, start_y, end_x, end_y);
if(check(start_x,start_y-1))
dfs(start_x, start_y - 1, end_x, end_y);
}
}
int main()
{
int i, j;
int start_x, start_y;
int end_x, end_y;
cin >> m >> n;
cin >> start_x >> start_y;
cin >> end_x >> end_y;
for (i = 0; i < m;i++)
{
for (j = 0; j < n;j++)
{
cin >> maze[i][j];
}
}
dfs(start_x, start_y, end_x, end_y);
if(flag)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
8皇后问题
描述
输出8皇后问题所有结果。
输入
没有输入。
输出
每个结果第一行是No n:的形式,n表示输出的是第几个结果;下面8行,每行8个字符,‘A’表示皇后,‘.’表示空格。不同的结果中,先输出第一个皇后位置靠前的结果;第一个皇后位置相同,先输出第二个皇后位置靠前的结果;依次类推。
输入样例
输出样例
输出的前几行:
No 1:
A…
…A…
…A
…A…
…A…
…A.
.A…
…A…
No 2:
A…
…A…
…A
…A…
…A.
…A…
.A…
…A…
#include <iostream>
#include <cmath>
int a[9];
int cnt;
using namespace std;
bool check(int x,int y)
{
int i;
for (i = 1; i < x;i++)
{
if(a[i] == y || abs(i - x) == abs(a[i] - y))
return false;
}
return true;
}
void display()
{
int i, j;
for (i = 1; i <= 8;i++)
{
for (j = 1; j <= 8;j++)
{
if(a[i] == j)
cout << 'A';
else
cout << '.';
}
cout << endl;
}
}
void dfs(int i)
{
if(i == 9)
{
cnt++;
cout << "No " << cnt + 1 << ":" << endl;
display();
}
else{
int j;
for (j = 1; j <= 8;j++)
{
if(check(i,j))
{
a[i] = j;
dfs(i + 1);
a[i] = 0;
}
}
}
}
int main()
{
dfs(1);
cout << cnt;
}
堡垒问题
描述
城堡是一个4×4的方格,为了保卫城堡,现需要在某些格子里修建一些堡垒。城堡中的某些格子是墙,其余格子都是空格,堡垒只能建在空格里,每个堡垒都可以向上下左右四个方向射击,如果两个堡垒在同一行或同一列,且中间没有墙相隔,则两个堡垒都会把对方打掉。问对于给定的一种状态,最多能够修建几个堡垒。
输入
每个测例以一个整数n(1<=n<=4)开始,表示城堡的大小。接下来是n行字符每行n个,‘X’表示该位置是墙,‘.’表示该位置是空格。n等于0标志输入结束。
输出
每个测例在单独的一行输出一个整数:最多修建堡垒的个数。
输入样例
4
.X…
…
XX…
…
2
XX
.X
3
.X.
X.X
.X.
3
…
.XX
.XX
4
…
…
…
…
0
输出样例
5
1
5
2
4
#include <iostream>
using namespace std;
#define MAX 4
int n;
char maze[MAX][MAX];
int cnt;
int mmax;
bool collide(int row ,int col)
{
int i;
for (i = col; i >= 0;i--)
{
if(maze[row][i] == 'T')
return false;
if(maze[row][i] == 'X')
break;
}
for (i = row; i >= 0;i--)
{
if(maze[i][col] == 'T')
return false;
if(maze[i][col] == 'X')
break;
}
if(maze[row][col] == 'X')
return false;
return true;
}
void dfs(int i)
{
int row = i / n;
int col = i % n;
int j, k;
if(i == n * n)
{
int num = 0;
for (j = 0; j < n;j++)
{
for (k = 0; k < n;k++)
{
if(maze[j][k] == 'T')
num++;
}
}
if(num > mmax)
{
mmax = num;
}
}
else{
dfs(i + 1);
if(collide(row,col))
{
maze[row][col] = 'T';
dfs(i + 1);
maze[row][col] = '.';
}
}
}
int main()
{
int m[100];
while(cin>>n,n)
{
int i, j;
for (i = 0; i < n;i++)
{
for (j = 0; j < n;j++)
{
cin >> maze[i][j];
}
}
dfs(0);
m[cnt] = mmax;
mmax = 0;
cnt++;
}
int i;
for (i = 0; i < cnt;i++)
{
cout << m[i] << endl;
}
}
素数环问题
描述
把1到20这重新排列,使得排列后的序列A满足:
a. 任意相邻两个数之和是素数
b. 不存在满足条件a的序列B使得:A和B的前k(0 <= k <= 19)项相同且B的第k+1项比A的第k+1项小。(即按字典序排列的第一项)
输入
没有输入。
输出
输出A,两个数字之间用一个空格隔开,第一个数字前面和最后一个数字后面没有空格。
#include <iostream>
#include <cmath>
using namespace std;
int vis[21];
int a[21];
bool isprime(int num)
{
int i;
for (i = 2; i <= sqrt(num);i++)
{
if(num % i == 0)
return false;
}
return true;
}
bool check(int place,int num)
{
if(isprime(a[place - 1] + num) && !vis[num])
return true;
return false;
}
void display()
{
int i;
for (i = 1; i <= 20;i++)
{
cout << a[i] << " ";
}
cout << endl;
}
void dfs(int i)
{
if(i == 21)
{
if(isprime(a[1]+a[20]))
{
display();
exit(0);
}
}
else{
int j;
for (j = 1; j <= 20;j++)
{
if(check(i,j))
{
vis[j] = 1;
a[i] = j;
dfs(i + 1);
a[i] = 0;
vis[j] = 0;
}
}
}
}
int main()
{
dfs(1);
}
分支限界法复习
加1乘2平方
描述
最简单的队列的使用
#include
#include
using namespace std;
queue q1;
int main()
{
int temp, x;
q1.push(5);//入队
q1.push(8);//入队
temp = q1.front();//访问队首元素
q1.pop();//出队
q1.empty();//判队列是否为空
q1.back();//返回队尾元素
q1.size();//返回队列长度
}
给定两个正整数m、n,问只能做加1、乘2和平方这三种变化,从m变化到n最少需要几次
输入
输入两个10000以内的正整数m和n,且m小于n
输出
输出从m变化到n的最少次数
输入样例
1 16
输出样例
3
#include <iostream>
#include <queue>
using namespace std;
int vis[10001];
int step[10001];
int m, n;
bool check(int num)
{
if(vis[num] ||num > n)
return false;
return true;
}
int make_new_place(int root,int type)
{
switch (type)
{
case 0:
return root + 1;
case 1:
return root * 2;
case 2:
return root * root;
}
return 0;
}
void bfs(queue<int> q)
{
q.push(m);
while(!q.empty())
{
int pop_num = q.front();
q.pop();
int i;
int new_num[3];
for (i = 0; i < 3;i++)
{
new_num[i] = make_new_place(pop_num, i);
if(check(new_num[i]))
{
q.push(new_num[i]);
vis[new_num[i]] = pop_num;
step[new_num[i]] = step[pop_num] + 1;
if(new_num[i] == n)
return;
}
}
}
}
int main()
{
cin >> m >> n;
queue<int> q;
bfs(q);
cout << step[n] << endl;
}
电子老鼠闯迷宫
描述
有一只电子老鼠被困在如下图所示的迷宫中。这是一个12*12单元的正方形迷宫,黑色部分表示建筑物,白色部分是路。电子老鼠可以在路上向上、下、左、右行走,每一步走一个格子。现给定一个起点S和一个终点T,求出电子老鼠最少要几步从起点走到终点。
输入
本题包含一个测例。在测例的第一行有四个由空格分隔的整数,分别表示起点的坐标S(x.y)和终点的坐标T(x,y)。从第二行开始的12行中,每行有12个字符,描述迷宫的情况,其中’X’表示建筑物,’.'表示路.
输出
输出一个整数,即电子老鼠走出迷宫至少需要的步数。
输入样例
2 9 11 8
XXXXXXXXXXXX
X…X.XXX
X.X.XX…X
X.X.XX.XXX.X
X.X…X…X
X.XXXXXXXXXX
X…X.X…X
X.XXX…XXXX
X…X…X
XXX.XXXX.X.X
XXXXXXX…XXX
XXXXXXXXXXXX
输出样例
28
#include <iostream>
#include <queue>
using namespace std;
int walk[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
int maze[12][12];
int step[12 * 12];
int start_x, start_y, end_x, end_y;
void input()
{
cin >> start_x >> start_y;
cin >> end_x >> end_y;
start_x--;
start_y--;
end_x--;
end_y--;
int i, j;
char c;
for (i = 0; i < 12;i++)
{
for (j = 0; j < 12;j++)
{
cin >> c;
if(c == 'X')
maze[i][j] = 1;
}
}
}
int make_new_place(int row,int col,int type)
{
row += walk[type][0];
col += walk[type][1];
if(row >= 0 && row < 12 && col >= 0 && col <12 && maze[row][col] == 0)
{
return row * 12 + col;
}
return -1;
}
void bfs(queue<int>q)
{
q.push(start_x * 12 + start_y);
while(!q.empty())
{
int pop_num = q.front();
q.pop();
int place_r = pop_num / 12;
int place_c = pop_num % 12;
int new_num;
int i;
for (i = 0; i < 4;i++)
{
new_num = make_new_place(place_r, place_c, i);
if(new_num != -1)
{
int row = new_num / 12;
int col = new_num % 12;
maze[row][col] = pop_num;
step[new_num] = step[pop_num] + 1;
q.push(new_num);
if(row == end_x && col == end_y)
{
return;
}
}
}
}
}
int main()
{
input();
queue<int> q;
bfs(q);
cout << step[end_x * 12 + end_y] << endl;
}
动态规划复习
最长公共子序列
时限:1000ms 内存限制:200000K 总时限:3000ms
描述
一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X=<x1, x2,…, xm>,则另一序列Z=<z1, z2,…, zk>是X的子序列是指存在一个严格递增的下标序列 <i1, i2,…, ik>,使得对于所有j=1,2,…,k有:
Xij = Zj
如果一个序列S即是A的子序列又是B的子序列,则称S是A、B的公共子序列。
求A、B所有公共子序列中最长的序列的长度。
输入
输入共两行,每行一个由字母和数字组成的字符串,代表序列A、B。A、B的长度不超过200个字符。
输出
一个整数,表示最长各个子序列的长度。
格式:printf("%d\n");
输入样例
programming
contest
输出样例
2
#include <iostream>
#include <string>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
string a, b;
int dp[100][100];
void solve()
{
int m = a.length();
int n = b.length();
int i, j;
for (i = 1; i <= m;i++)
{
for (j = 1; j <= n;j++)
{
if(a[i-1] == b[j-1])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else{
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
}
int main()
{
cin >> a;
cin >> b;
solve();
cout << dp[a.length()][b.length()] << endl;
}
矩阵连乘
时限:1000ms 内存限制:10000K 总时限:3000ms
描述
在科学计算中经常要计算矩阵的乘积。矩阵A和B可乘的条件是矩阵A的列数等于矩阵B的行数。若A是一个p×q的矩阵,B是一个q×r的矩阵,则其乘积C=AB是一个p×r的矩阵。计算C=AB总共需要p×q×r次乘法。
现在的问题是,给定n个矩阵{A1,A2,…,An}。其中Ai与Ai+1是可乘的,i=1,2,…,n-1。
要求计算出这n个矩阵的连乘积A1A2…An最少需要多少次乘法。
输入
输入数据的第一行是一个整树n(0 < n <= 10),表示矩阵的个数。
接下来的n行每行两个整数p,q( 0 < p,q < 100),分别表示一个矩阵的行数和列数。
输出
输出一个整数:计算连乘积最少需要乘法的次数。
输入样例
10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
输出样例
438
#include <iostream>
#define MAX 1000000
using namespace std;
int N;
int p[101];
int dp[100][100];
void solve(int *p)
{
int i, j, k, t, temp;
for (i = 0; i <= N;i++)
{
dp[i][i] = 0;
}
for (t = 2; t <= N;t++)
{
for (i = 1; i <= N - t + 1; i++)
{
j = i + t - 1;
dp[i][j] = MAX;
for (k = i; k < j;k++)
{
temp = dp[i][k] + dp[k + 1][j] + p[i - 1] * p[k] * p[j];
if(temp < dp[i][j])
{
dp[i][j] = temp;
}
}
}
}
}
int main()
{
int i;
cin >> N;
for (i = 0; i < N;i++)
{
cin >> p[i] >> p[i + 1];
}
solve(p);
cout << dp[1][N] << endl;
}
防卫导弹
描述
一种新型的防卫导弹可截击多个攻击导弹。它可以向前飞行,也可以用很快的速度向下飞行,可以毫无损伤地截击进攻导弹,但不可以向后或向上飞行。但有一个缺点,尽管它发射时可以达到任意高度,但它只能截击比它上次截击导弹时所处高度低或者高度相同的导弹。现对这种新型防卫导弹进行测试,在每一次测试中,发射一系列的测试导弹(这些导弹发射的间隔时间固定,飞行速度相同),该防卫导弹所能获得的信息包括各进攻导弹的高度,以及它们发射次序。现要求编一程序,求在每次测试中,该防卫导弹最多能截击的进攻导弹数量,一个导弹能被截击应满足下列两个条件之一:
a)它是该次测试中第一个被防卫导弹截击的导弹;
b)它是在上一次被截击导弹的发射后发射,且高度不大于上一次被截击导弹的高度的导弹。
输入
多个测例。
每个测例第一行是一个整数n(n不超过100),第二行n个整数表示导弹的高度(数字的顺序即发射的顺序)。
n=0表示输入结束。
输出
每个测例在单独的一行内输出截击导弹的最大数目。
输入样例
5
5 6 100 6 61
0
输出样例
2
#include <iostream>
#include <cstring>
#define max(a,b) (((a)>(b))?(a):(b))
using namespace std;
int mmax;
int n;
int dp[100];
void solve(int *a)
{
int i, j;
for (i = 0; i < n;i++)
{
dp[i] = 1;
for (j = 0; j < i;j++)
{
if(a[i] <= a[j])
{
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
for (i = 0; i < n;i++)
mmax = max(mmax, dp[i]);
}
int main()
{
int i;
int a[100];
while(cin>>n,n)
{
for (i = 0; i < n;i++)
{
cin >> a[i];
}
solve(a);
cout << mmax << endl;
mmax = 0;
memset(a, 0, sizeof(a));
memset(dp, 0, sizeof(dp));
}
}
最大连续子序列和问题
时限:1000ms 内存限制:10000K 总时限:3000ms
描述
给定一整数序列A0,A1, A2,… An-1 (可能有负数),求A0An-1的一个连续子序列AiAj,使得Ai到Aj的和最大。
输入
先输入一个正整数n(1<n<1000),再输入n个整数。
输出
输出最大连续子序列的和。
输入样例
10
2 -1 5 -7 2 -1 4 -2 4 -5
输出样例
7
#include <iostream>
#define max(a,b) ((a>b)?(a):(b))
using namespace std;
int mmax;
int dp[1000];
int n;
void solve(int *a)
{
int i;
if(a[0] >= 0)
dp[0] = a[0];
else
dp[0] = 0;
for (i = 1; i < n;i++)
{
dp[i] = max(a[i], dp[i - 1] + a[i]);
if(dp[i] > mmax)
{
mmax = dp[i];
}
}
}
int main()
{
cin >> n;
int i;
int a[1000];
for (i = 0; i < n;i++)
{
cin >> a[i];
}
solve(a);
cout << mmax << endl;
}
贪心法复习
活动安排
描述
Jack是一名nwpu的大一新生,对学校举办的各种活动都十分的好奇,想尽可能多的参加这些活动。Npwu每天共有N项活动,其开始结束时间分别为B[i],E[i],(i = 1,2,……N)
请问Jack一天最多能参加几项活动。当然,Jack在同一时间内只能参加一项活动,即jack参加的活动时间上不能重叠,但时间为[t1,t2],[t2,t3]的两个活动是可以同时参加的。
输入
第一行 一个整数N(1<=n<=1000)表示活动总数。
接下来N行表示各活动的起始,结束时间0<=B[i]<E[i]<24
输出
一个整数表示Jack最多能参加的活动数目。
输入样例
4
10 11
2 3
8 10
0 2
输出样例
4
#include <iostream>
#include <algorithm>
using namespace std;
struct Action{
int begin;
int end;
};
Action A[100];
int n;
int cnt;
bool cmp(Action s1,Action s2)
{
if(s1.end == s2.end)
{
return s1.begin <= s2.begin;
}
else{
return s1.end < s2.end;
}
}
void solve()
{
sort(A + 1, A + n + 1, cmp);
int i;
int preend = 0;
for (i = 1; i <= n;i++)
{
if(preend <= A[i].begin)
{
preend = A[i].end;
cnt++;
}
}
}
int main()
{
int i;
cin >> n;
for (i = 0; i < n;i++)
{
cin >> A[i].begin >> A[i].end;
}
solve();
cout << cnt << endl;
}
田忌赛马
时限:1000ms 内存限制:10000K 总时限:3000ms
描述
田忌与齐王赛马,双方各有n匹马参赛(n<=100),每场比赛赌注为1两黄金,现已知齐王与田忌的每匹马的速度,并且齐王肯定是按马的速度从快到慢出场,现要你写一个程序帮助田忌计算他最好的结果是赢多少两黄金(输用负数表示)。
Tian Ji and the king play horse racing, both sides have n horse (n is no more the 100), every game a bet of 1 gold, now known king and Tian Ji each horse’s speed, and the king is definitely on the horse speed from fast to slow, we want you to write a program to help Tian Ji his best result is win the number gold (lost express with the negative number).
输入
多个测例。
每个测例三行:第一行一个整数n,表示双方各有n匹马;第二行n个整数分别表示田忌的n匹马的速度;第三行n个整数分别表示齐王的n匹马的速度。
n=0表示输入结束。
A plurality of test cases.
Each test case of three lines: the first line contains an integer n, said the two sides each have n horse; second lines of N integers n Tian Ji horse speed; third lines of N integers King n horse speed.
N = 0 indicates the end of input.
输出
每行一个整数,田忌最多能赢多少两黄金。
how many gold the tian ji win
输入样例
3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
3
20 20 10
20 20 10
0
#include <iostream>
#include <algorithm>
#define MAX 101
using namespace std;
int n;
int a[MAX];
int b[MAX];
int cnt;
int e;
bool compare(int a,int b)
{
return a > b;
}
void solve()
{
sort(a, a + n, compare);
sort(b, b + n, compare);
int a1 = 0;
int b1 = 0;
int m1 = n - 1;
int n1 = n - 1;
int t = 0;
while(a1 <= m1)
{
if(a[m1] > b[n1])
{
m1--;
n1--;
t++;
}
else if(a[m1] < b[n1])
{
m1--;
b1++;
t--;
}
else if(a[a1] > b[b1])
{
a1++;
b1++;
t++;
}
else{
if(a[m1] > b[b1])
{
m1--;
b1++;
t++;
}
else if(a[m1] < b[b1])
{
b1++;
m1--;
t--;
}
else{
b1++;
m1--;
}
}
}
cnt = t;
}
void input()
{
int i;
for (i = 0; i < n;i++)
{
cin >> a[i];
}
for (i = 0; i < n;i++)
{
cin >> b[i];
}
}
int main()
{
while(cin>>n,n)
{
input();
solve();
cout << cnt << endl;
cnt = 0;
e = 0;
}
}