1>思维
输入一个字符串,求它包含多少个单词。单词间以一个或者多个空格分开。
第一个单词前,最后一个单词后也可能有0到多个空格。
比如:" abc xyz" 包含两个单词,"ab c xyz " 包含3个单词。
如下的程序解决了这个问题,请填写划线部分缺失的代码。
注意:只填写划线部分的代码,不要填写任何多余的内容。比如已经存在的小括号,注释或说明文字等。
int get_word_num(char* buf)
{
int n = 0;
int tag = 1;
char* p = buf;
for(;*p!=0 && *p!=13 && *p!=10;p++){
if(*p==' ' && tag==0) tag=1;
if( _____________________ ) { n++; tag=0; } //填空
}
return n;
}
int main()
{
char buf[1000];
fgets(buf,1000,stdin);
printf("%d
", get_word_num(buf));
return 0;
}
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; int get_word_num(char* buf) { int n = 0; int tag = 1; char* p = buf; for (; *p != 0 && *p != 13 && *p != 10; p++) {//枚举 if (*p == ' ' && tag == 0) tag = 1; //如果是' '并且上一个不是' ' if (tag == 1 && *p != ' ') { n++; tag = 0; } //若果当前不是' '并且上一个是' ' } return n; } int main() { char buf[1000]; fgets(buf, 1000, stdin); printf("%d ", get_word_num(buf)); return 0; }
2>小数运算
1/1 + 1/2 + 1/3 + 1/4 + ... 在数学上称为调和级数。
它是发散的,也就是说,只要加上足够多的项,就可以得到任意大的数字。
但是,它发散的很慢:
前1项和达到 1.0
前4项和才超过 2.0
前83项的和才超过 5.0
那么,请你计算一下,要加多少项,才能使得和达到或超过 15.0 呢?
请填写这个整数。
注意:只需要填写一个整数,不要填写任何多余的内容。比如说明文字。
#include<iostream> #include<algorithm> using namespace std; int main() { double cnt = 0; for (int i = 1; i < 10000000; i++) { cnt += 1.0 / (double)i; if (cnt >= 15.0) { cout << i << " "; break; } } return 0; } //输出:1835421
3> 小数运算+四舍五入/小数二分
如果x的x次幂结果为10(参见【图1.png】),你能计算出x的近似值吗?
显然,这个值是介于2和3之间的一个数字。
请把x的值计算到小数后6位(四舍五入),并填写这个小数值。
注意:只填写一个小数,不要写任何多余的符号或说明。
【图1.png】:
方法一:小数二分
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; void erf() {//方法一 double le = 2.0, ri = 3.0, mid; for (int i = 1; i<200; i++)//小数二分搜索 if (le< ri) { mid = (le + ri) / 2.0; if (pow(mid, mid) >= 9.99999999&&pow(mid, mid) <= 10.00000001)break; else if (pow(mid, mid) < 10.0)le = mid; else ri = mid; } printf("%.10f ", mid); } int main() { erf(); return 0; } // 结果:2.5061841458 答案保留六位即可
方法二:枚举
#include<iostream> #include<algorithm> #include<math.h> using namespace std; void so() { double x; for (x = 2.0; x<3.0; x += 0.00000001)//枚举 { if (abs(pow(x, x) - 10.0)<0.000001) printf("%.10f ", x); } } int main() { so(); return 0; } // 结果: //2.5061840969 //2.5061841069 //2.5061841169 //2.5061841269 //2.5061841369 //2.5061841469 //2.5061841569 //2.5061841669 //2.5061841769 //2.5061841869 //2.5061841969
//答案保留六位即可
4> dfs/全排列
今有7对数字:两个1,两个2,两个3,...两个7,把它们排成一行。
要求,两个1间有1个其它数字,两个2间有2个其它数字,以此类推,两个7之间有7个其它数字。如下就是一个符合要求的排列:
17126425374635
当然,如果把它倒过来,也是符合要求的。
请你找出另一种符合要求的排列法,并且这个排列法是以74开头的。
注意:只填写这个14位的整数,不能填写任何多余的内容,比如说明注释等。
方法一:dfs
#include<iostream> #include<algorithm> using namespace std; int a[16], book[8];//a[i]代表第i个数 book[i]代表i是否用过 void dfs(int ans) {//ans代表当前第几个 if (ans == 15) { for (int i = 1; i < 15; i++) cout << a[i]; cout << " "; return; } if (a[ans] != 0)dfs(ans + 1); for (int i = 1; i < 7; i++) {//依次枚举当前放数字几 if (book[i] == 0 && a[ans] == 0 && a[ans + i + 1] == 0) { a[ans] = a[ans + i + 1] = i;//放入i book[i] = 1;//标记i已用 dfs(ans + 1); book[i] = 0; a[ans] = a[ans + i + 1] = 0; } } } int main() { book[4] = 1; book[7] = 1; a[1] = a[9] = 7; a[2] = a[7] = 4;//搜索前一定要把标记的先标记上 dfs(3); return 0; } //74151643752362
方法二:全排列
#include<iostream> #include<algorithm> using namespace std; void p() {//全排列方法 速度慢 int b[15] = { 7,4,1,1,2,2,4,3,7,3,5,5,6,6 };//把数都导入 bool book2[15]; while (next_permutation(b + 2, b + 14)) {//全排列函数 memset(book2, 0, sizeof(book2)); int i; for (i = 0; i < 14; i++) {//枚举每个位置 if (book2[i])continue; else { if (b[i] == b[i + b[i] + 1]) book2[i + b[i] + 1] = true; else break; } } if (i == 14) {//满足条件就输出 for (i = 0; i < 14; i++) cout << b[i]; cout << " "; break; } } } int main() { p(); return 0; } //74151643752362
5>思维
勾股定理,西方称为毕达哥拉斯定理,它所对应的三角形现在称为:直角三角形。
已知直角三角形的斜边是某个整数,并且要求另外两条边也必须是整数。
求满足这个条件的不同直角三角形的个数。
【数据格式】
输入一个整数 n (0<n<10000000) 表示直角三角形斜边的长度。
要求输出一个整数,表示满足条件的直角三角形个数。
例如,输入:
5
程序应该输出:
1
再例如,输入:
100
程序应该输出:
2
再例如,输入:
3
程序应该输出:
0
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
#include <iostream> #include <algorithm> #include<math.h> using namespace std; #define ll long long ll a[100001]; int main() { ll n,x,y,cnt = 0; cin >> n; for (int i = 1; i<n / sqrt(2); i++)//根据三角形构成条件,缩小范围 { x = i*i; y = sqrt(n*n - x); if (x+y*y== n*n)cnt++; } cout << cnt << endl; }
6>dfs
你一定听说过“数独”游戏。
玩家需要根据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
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 2000ms
#include<iostream> #include<algorithm> #include<string> using namespace std; char t[20][20]; //a:每个格的数 kx[][]:记录横向数是否已用 ky[][]:记录横向数是否已用 kj[][]:记录九宫格是否已用 int a[20][20], kx[20][20], ky[20][20],kj[20][20],ans=0; void dfs(int x, int y) { //cout << "(" << x << "," << y << ")" << " "; if (ans)return; if (x == 10) { ans = 1; for (int i = 1; i < 10; i++) { for (int j = 1; j < 10; j++) cout << a[i][j]; cout << " "; } return; } if (a[x][y] == 0) { for (int i = 1; i<10; i++) if (kx[x][i] == 0 && ky[y][i] == 0&& kj[(x - 1) / 3 * 3 + (y + 2) / 3][i] ==0) { kj[(x - 1) / 3 * 3 + (y + 2) / 3][i] = 1; kx[x][i] = 1; ky[y][i] = 1; a[x][y] = i; if (y == 9)dfs(x + 1, 1); else dfs(x, y + 1); a[x][y] = 0; kx[x][i] = 0; ky[y][i] = 0; kj[(x - 1) / 3 * 3 + (y + 2) / 3][i] = 0; } } else { if (y == 9)dfs(x + 1, 1); else dfs(x, y + 1); } return; } int main() { for (int i = 1; i < 10; i++) { for (int j = 1; j < 10; j++) { cin >> t[i][j]; a[i][j] = t[i][j] - '0'; if (a[i][j] != 0) { kx[i][a[i][j]] = 1; ky[j][a[i][j]] = 1; kj[(i-1)/3*3+(j+2)/3][a[i][j]] = 1;//巧妙地是这里,将九大块刚好编号为1~9 } } } cout << " "; dfs(1, 1); return 0; }
7:dp
参考博文:https://blog.csdn.net/dodd9199/article/details/41916121
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. 选1;
2. 选2;
3. 选3;
4. 选2, 3。
样例输入2
7
1 1 2 2 3 3
样例输出2
40
数据规模与约定
对于20%的数据,n ≤ 20;
对于40%的数据,n ≤ 100;
对于100%的数据,1 ≤ n ≤ 100000。
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 2000ms
#include <iostream> #include<algorithm> #include<vector> using namespace std; int n,dp[100010][2],t; vector<int>v[100010]; int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin >> n; for (int i = 2; i <= n; i++) { cin >> t; v[t].push_back(i); } for (int i = n; i > 0; i--) { //从下向上 dp[i][0] = 1; //初始化 dp[i][1] = 1; //初始化 for (int j = 0; j < v[i].size(); j++) { dp[i][0] *= (dp[v[i][j]][0] + dp[v[i][j]][1]);//下级(去+不去) 的累乘 dp[i][1] *= dp[v[i][j]][0];//下级(不去)的累乘 dp[i][0] %= 10007; dp[i][1] %= 10007; } } cout << dp[1][1] + dp[1][0] - 1 << " ";//减去都不去的情况 return 0; }