第一题:
一个串的子串是指该串的一个连续的局部。如果不要求连续,则可称为它的子序列。
比如对串: “abcdefg” 而言,“ab”,“abd”,“bdef” 等都是它的子序列。
特别地,一个串本身,以及空串也是它的子序列。
对两个串而言,可以有许多的共同的子序列,我们关心的是:它们所共同拥有的长度最大的子序列是多长。以下代码实现了这个问题的求解。请填写划线部分缺失的代码。
注意:只填写划线部分缺少的内容,不要填写任何多余的符号或注释、说明等。例如,不要填写已经给出的小括号。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 1e5 + 10;
int max(int a, int b)
{
return a>b?a:b;
}
int f(char* x, char* y)
{
if(strlen(x)==0) return 0;
if(strlen(y)==0) return 0;
if(*x == *y) return f(x+1, y+1) + 1;
return max(_______________________);
//f(x + 1, y), f(x, y + 1)
}
int main()
{
printf("%d\n", f("ac","abcd")); //2
printf("%d\n", f("acebbcde1133","xya33bc11de")); //5
return 0;
}
第二题:
历史上有许多计算圆周率pai的公式,其中,格雷戈里和莱布尼茨发现了下面的公式:
pai = 4*(1-1/3+1/5-1/7 …)
参见【图1.png】
这个公式简单而优美,但美中不足,它收敛的太慢了。
如果我们四舍五入保留它的两位小数,那么:
累积了1项和是:4.00
累积了2项和是:2.67
累积了3项和是:3.47
。。。
请你写出它累积了100项的和是多少(四舍五入到小数后两位)。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 1e5 + 10;
int main()
{
double pi = 1;
int sign = -1;
int cnt = 1;
for(int i = 3; i <= 199; i += 2)
{
if(cnt % 2)
pi += sign * (double)1.0 / i;
else
pi += (double)1.0 / i;
cnt ++ ;
}
printf("%.2lf\n", pi * 4);//3.13
return 0;
}
第三题:
如果x的x次幂结果为10(参见【图1.png】),你能计算出x的近似值吗?
显然,这个值是介于2和3之间的一个数字。
请把x的值计算到小数后6位(四舍五入),并填写这个小数值。
注意:只填写一个小数,不要写任何多余的符号或说明。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
double x = 2.0;
while(x < 3.0)
{
x = x + 0.00000001;
if(fabs(pow(x, x) - 10.0) < 0.000001)
{
printf("%.8lf\n", x);
}
}
return 0;
}
第四题:
今有7对数字:两个1,两个2,两个3,…两个7,把它们排成一行。
要求,两个1间有1个其它数字,两个2间有2个其它数字,以此类推,两个7之间有7个其它数字。如下就是一个符合要求的排列:
17126425374635
当然,如果把它倒过来,也是符合要求的。
请你找出另一种符合要求的排列法,并且这个排列法是以74开头的。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 1e5 + 10;
int a[] = {
0, 7, 4, 0, 0, 0, 0, 4, 0, 7, 0, 0, 0, 0, 0};
void dfs(int n)
{
if(n == 4) dfs(n + 1);
if(n == 7)
{
for(int i = 1; i <= 14; i ++ ) printf("%d", a[i]);
puts("");
}
for(int i = 3; i <= 14; i ++ )
{
if(i == 7 || i == 9) continue;
int p = n + i + 1;
if(p > 14) continue;
if(a[i] == 0 && a[p] == 0)
{
a[i] = n, a[p] = n;
dfs(n + 1);
a[i] = 0, a[p] = 0;
}
}
}
int main()
{
dfs(1);
return 0;
}
第五题:
勾股定理,西方称为毕达哥拉斯定理,它所对应的三角形现在称为:直角三角形。
已知直角三角形的斜边是某个整数,并且要求另外两条边也必须是整数。
求满足这个条件的不同直角三角形的个数。
【数据格式】
输入一个整数 n (0<n<10000000) 表示直角三角形斜边的长度。
要求输出一个整数,表示满足条件的直角三角形个数。
例如,输入:
5
程序应该输出:
1
再例如,输入:
100
程序应该输出:
2
再例如,输入:
3
程序应该输出:
0
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
int res = 0;
for(int i = 3; i < n; i ++ )
{
int a = (int)sqrt(n * n - i * i);
if(a * a + i * i == n * n) res ++ ;
}
printf("%d\n", res / 2);
return 0;
}
第六题:
你一定听说过“数独”游戏。
如【图1.png】,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。
数独的答案都是唯一的,所以,多个解也称为无解。
本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目。但对会使用计算机编程的你来说,恐怕易如反掌了。
本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。
格式要求:
输入9行,每行9个数字,0代表未知,其它数字为已知。
输出9行,每行9个数字表示数独的解。
例如:
输入(即图中题目):
005300000
800000020
070010500
400005300
010070006
003200080
060500009
004000030
000009700
程序应该输出:
145327698
839654127
672918543
496185372
218473956
753296481
367542819
984761235
521839764
再例如,输入:
800000000
003600000
070090200
050007000
000045700
000100030
001000068
008500010
090000400
程序应该输出:
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452
#include <iostream>
#include <cstring>
using namespace std;
const int N = 9, M = 1 << N;
int row[N], col[N], cell[N][N];
int ones[M], map[M];
char str[100][100];
void init()
{
for(int i = 0; i < N; i ++ )
row[i] = col[i] = (1 << N) - 1;
for(int i = 0; i < 3; i ++ )
for(int j = 0; j < 3; j ++ )
cell[i][j] = (1 << N) - 1;
}
void draw(int x, int y, int t, bool is_set)
{
if(is_set) str[x][y] = t + '1';
else str[x][y] = '0';
int v = 1 << t;
if(!is_set) v = -v;
row[x] -= v;
col[y] -= v;
cell[x / 3][y / 3] -= v;
}
int lowbit(int x)
{
return x & -x;
}
int get(int x, int y)
{
return row[x] & col[y] & cell[x / 3][y / 3];
}
bool dfs(int cnt)
{
if(!cnt) return true;
int minv = 10;
int x, y;
for(int i = 0 ; i < N; i ++ )
for(int j = 0; j < N; j ++ )
{
if(str[i][j] == '0')
{
int state = get(i, j);
if(ones[state] < minv)
{
minv = ones[state];
x = i, y = j;
}
}
}
int state = get(x, y);
for(int i = state; i; i -= lowbit(i))
{
int t = map[lowbit(i)];
draw(x, y, t, true);
if(dfs(cnt - 1)) return true;
draw(x, y, t, false);
}
return false;
}
int main()
{
int n = 9;
int m = 9;
for(int i = 0; i < N; i ++ ) map[1 << i] = i;
for(int i = 0; i < 1 << N; i ++ )
for(int j = 0; j < N; j ++ )
ones[i] += (i >> j & 1);
init();
for(int i = 0; i < n; i ++ )
scanf("%s", str[i]);
int cnt = 0;
for(int i = 0; i < N; i ++ )
for(int j = 0; j < N; j ++ )
if(str[i][j] != '0')
{
int t = str[i][j] - '1';
draw(i, j, t, true);
}
else cnt ++ ;
dfs(cnt);
for(int i = 0; i < n; i ++ )
{
printf("%s", str[i]);
puts("");
}
return 0;
}
第七题:
G将军有一支训练有素的军队,这个军队除开G将军外,每名士兵都有一个直接上级(可能是其他士兵,也可能是G将军)。现在G将军将接受一个特别的任务,需要派遣一部分士兵(至少一个)组成一个敢死队,为了增加敢死队队员的独立性,要求如果一名士兵在敢死队中,他的直接上级不能在敢死队中。
请问,G将军有多少种派出敢死队的方法。注意,G将军也可以作为一个士兵进入敢死队。
输入格式
输入的第一行包含一个整数n,表示包括G将军在内的军队的人数。军队的士兵从1至n编号,G将军编号为1。
接下来n-1个数,分别表示编号为2, 3, …, n的士兵的直接上级编号,编号i的士兵的直接上级的编号小于i。
输出格式
输出一个整数,表示派出敢死队的方案数。由于数目可能很大,你只需要输出这个数除10007的余数即可。
样例输入1
3
1 1
样例输出1
4
样例说明
这四种方式分别是:
- 选1;
- 选2;
- 选3;
- 选2, 3。
样例输入2
7
1 1 2 2 3 3
样例输出2
40
解析:
把父节点和子节点分开就可以很好地计算,利用递归即可
#include<stdio.h>
#include<string.h>
int a[100001],b[100001];
int n,t;
int str(int i)
{
if(i>n) //假如已经将n名士兵遍历一遍,就加一
{
t++;
return t;
}
if(a[b[i]]==0) //假如第i名士兵的直接上级已经出列
{
str(i+1); //那么这名士兵就不能出列,直接跳到下一位
}
else //假如第i名士兵的直接上级没有出列
{
a[i]=0; //让他出列并跳到下一位
str(i+1);
a[i]=i; //不让他出列并跳到下一位
str(i+1);
}
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
t=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
a[0]=1;
for(i=1;i<=n;i++)
{
a[i]=i; //储存当前状态,如果已经出列就置为0
}
b[1]=0;
for(i=2;i<=n;i++)
{
scanf("%d",&b[i]); //记录第i号士兵的直接上级
}
printf("%d\n",(str(1)-1)%10007); //因为要排除没有人去的情况,所以要减一
}
return 0;
}