第六章 函数¶
第一节 函数¶
1150:求正整数 2 和 n 之间的完全数¶
代码
1151:素数个数¶
代码
#include <bits/stdc++.h>
using namespace std;
bool is_prime(int x) {
if (x < 2) return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0) return false;
return true;
}
int main() {
int n;
cin >> n;
int cnt = 0;
for (int i = 2; i <= n; i++)
if (is_prime(i)) cnt++;
cout << cnt << endl;
return 0;
}
1152:最大数 max (x,y,z)¶
代码
1153:绝对素数¶
代码
1154:亲和数¶
代码
#include <bits/stdc++.h>
using namespace std;
int f(int x) {
int s = 0;
for (int i = 1; i <= x / i; i++) {
if (x % i == 0) {
if (i != 1) s += i + x / i;
else s += 1;
}
}
return s;
}
int main() {
int x = 2;
while (1) {
int a = x;
int b = f(a);
if (f(b) == a && a < b) {
cout << a << ' ' << b << endl;
break;
}
x++;
}
return 0;
}
1155:回文三位数¶
提示
prime,质数
palindrome,回文
代码
#include <bits/stdc++.h>
using namespace std;
bool is_palindrome(int x) {
int ori = x;
int t = 0;
while (x) {
t = t * 10 + x % 10;
x /= 10;
}
if (ori == t) return true;
else return false;
}
bool is_prime(int x) {
if (x < 2) return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0) return false;
return true;
}
int main() {
for (int i = 100; i < 1000; i++) {
if (is_palindrome(i) && is_prime(i)) {
cout << i << endl;
}
}
return 0;
}
1156:求 π 的值¶
提示
这个题目,有点饶一点
首先是这两个公式,看不懂。arctanx(x) 是一个多项式
当x取 \(\frac{1}{\sqrt{3}}\) 时,算出来 \(\pi\)
代码
// 求当最后一项小于10?6时π的值。
// 多项式的最后一项,是>=1e-6的
// 小于1e-6就不要加进来
#include <iostream>
#include <cmath>
using namespace std;
double arctanx(double x) {
double ret = 0.0;
double fenzi = x;
int t = -1, fenmu = 1;
while (true) {
t *= -1;
ret += t * fenzi / fenmu;
fenzi *= x * x;
fenmu += 2;
if (fenzi / fenmu < 1e-6) break;
}
return ret;
}
int main() {
printf("%.10lf\n", 6 * arctanx(1.0 / sqrt(3)));
return 0;
}
1157:哥德巴赫猜想¶
代码
#include<iostream>
using namespace std;
bool is_prime(int n){
if (n < 2) return false;
for (int i = 2; i <= n / i; i++)
if (n % i == 0) return false;
return true;
}
int main(){
for (int x = 6; x <= 100; x += 2){
bool flag = false;
for (int i = 2; i <= x; i++){
int j = x - i;
if (is_prime(i) && is_prime(j)){
cout << x << '=' << i << '+' << j << '\n';
flag = true;
break;
}
if (flag) break;
}
}
return 0;
}
1397:简单算术表达式求值¶
提示
两位正整数的简单算术运算
注意,两个整数,都是两位数,有了这个前提条件,输入上,才好处理
代码
#include <bits/stdc++.h>
using namespace std;
int a, b;
char c;
int main() {
scanf("%2d%c%2d", &a, &c, &b);
if (c == '+') cout << a + b << '\n';
else if (c == '-') cout << a - b << '\n';
else if (c == '*') cout << a * b << '\n';
else if (c == '/') cout << a / b << '\n';
else cout << a % b << '\n';
return 0;
}
代码02
// 如果没注意到两个整数的位数,是固定两位的,
// 或者题目就没说几位数的时候
// 那就需要把这一行当成一个字符串输入,然后手动拆出来
// 下面这份代码的写法,要掌握,【必会技能】
#include <bits/stdc++.h>
using namespace std;
string a, b;
char op;
int f(string s) {
int t = 0;
for (int i = 0, len = s.size(); i < len; i++)
t = t * 10 + (s[i] - '0');
return t;
}
int main() {
string s;
getline(cin, s);
int len = s.size();
int pos;
a += s[pos++];
a += s[pos++];
while (pos < len && s[pos] == ' ') pos++;
op = s[pos++];
while (pos < len && s[pos] == ' ') pos++;
b += s[pos++];
b += s[pos++];
int aa = f(a);
int bb = f(b);
//printf("---%d %d\n", aa, bb);
if (op == '+') cout << aa + bb << endl;
else if (op == '-') cout << aa - bb << endl;
else if (op == '*') cout << aa * bb << endl;
else if (op == '/') cout << aa / bb << endl;
else if (op == '%') cout << aa % bb << endl;
return 0;
}
1398:短信计费¶
代码
1399:甲流病人初筛¶
代码
1400:统计单词数¶
提示
此题对代码能力要求高一点
抠单词是一个基本功
此题,对.find()函数熟悉的,会好写一点
代码
// 这份代码,就是利用抠单词的基本功
// 直接抠就行了
#include<bits/stdc++.h>
using namespace std;
string st1,st2;
void solve() {
for(int i = 0, len = st1.size(); i < len; i++)
if(st1[i] >= 'A' && st1[i] <= 'Z') st1[i] += 32;
for(int i = 0, len = st2.size(); i < len; i++)
if(st2[i] >= 'A' && st2[i] <= 'Z') st2[i] += 32;
}
int main() {
int a=0,b=-1;
getline(cin,st1);
getline(cin,st2);
solve();
for(int i = 0, len = st2.size(); i < len; i++) {
string s="";
int j = i;
while (j < len && st2[j] != ' ') s += st2[j++];
if(s == st1) {
a++;
if(b == -1) b = i;
}
while(j < len && st2[j] == ' ') j++;
i = j - 1;
}
if(b == -1) cout<<-1 << '\n';
else cout<<a<<' '<<b << '\n';
return 0;
}
代码02
// 这份代码是,利用.find()函数
// .find()函数有一个参数的版本,有两个参数的版本
// 两个参数的,就是指定从哪个位置开始往后找
// 这样就形成了,找到一个,就从这个位置下一个位置开始往后找
// 代码就好写了
#include<iostream>
using namespace std;
string s, s1;
void get_lower(string &s) {
for (int i = 0, len = s.size(); i < len; i++)
if (s[i] >= 'A' && s[i] <= 'Z') s[i] += 32;
}
int main() {
cin >> s;
getchar();
getline(cin, s1);
get_lower(s);
get_lower(s1);
s = ' ' + s + ' ';
s1 = ' ' + s1 + ' ';
if (s1.find(s) == string::npos) {
cout << -1 << '\n';
return 0;
}
int tot = 0, fir = s1.find(s);
int nxt = fir;
while (nxt != -1) {
tot++;
nxt = s1.find(s, nxt + 1);
}
cout << tot << ' ' << fir << '\n';
return 0;
}
1401:机器翻译¶
代码
// 用到了queue
// 用bool数组,或者map是否在内存里
#include <iostream>
#include <queue>
using namespace std;
int m, n, cnt;
queue<int> q;
bool vis[1010];
int main() {
cin >> m >> n;
while (n--) {
int x;
cin >> x;
if (vis[x]) continue;
cnt++;
if (q.size() == m) {
int t = q.front();
q.pop();
vis[t] = false;
}
q.push(x);
vis[x] = true;
}
cout << cnt << '\n';
return 0;
}
1402:Vigenère 密码¶
提示
Helloworld
abcabcabca
Hfnlpyosnd
题面给的数据有误
代码
#include <bits/stdc++.h>
using namespace std;
string K, C;
int main() {
cin >> K >> C; // K是密钥,C是密文
int idx = 0, klen = K.size();
string s;
for (int i = 0, len = C.size(); i < len; i++) {
char c = K[idx]; // 把密钥的字符拿出来, 计算偏移量
int delta = 0;
if (c >= 'A' && c <= 'Z') delta = c - 'A';
if (c >= 'a' && c <= 'z') delta = c - 'a';
char mc = C[i]; // 把密文的字符拿出来,按偏移量进行操作
if (mc >= 'A' && mc <= 'Z') s += 'A' + (mc - 'A' - delta + 26) % 26;
if (mc >= 'a' && mc <= 'z') s += 'a' + (mc - 'a' - delta + 26) % 26;
// 这里面有+26 %26,是为了防止向左偏移减成负数
idx++;
if (idx >= klen) idx = 0; // 这个是用来循环使用密钥的
}
cout << s << endl;
return 0;
}
1403:素数对¶
提示
先用筛法,把所有质数放到一起
然后捋一遍,看前后是否相差2
这里用的是埃式筛法(以后还要学习一个线性筛法)
代码
#include<bits/stdc++.h>
using namespace std;
bool st[100010];
int primes[100010], cnt, n, maxn = 10010;
void get_primes(int n) {
for(int i = 2; i <= n; i++) {
if(st[i]) continue;
primes[cnt++] = i;
for(int j = i + i; j <= n; j +=i) {
st[j] = true;
}
}
}
int main() {
cin >> n;
get_primes(n);
bool flag = false;
for(int i = 1; i < cnt; i++) {
if (primes[i] - primes[i - 1] == 2) {
cout << primes[i - 1] <<' '<< primes[i] <<'\n';
flag = true;
}
}
if (!flag) cout << "empty" << endl;
return 0;
}
1404:我家的门牌号¶
代码
1405:质数的和与积¶
代码
#include <bits/stdc++.h>
using namespace std;
bool is_prime(int x) {
if (x < 2) return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0) return false;
return true;
}
int main() {
int n;
cin >> n;
int maxn = -1;
for (int i = 2; i <= n - 2; i++)
if (is_prime(i) && is_prime(n - i))
maxn = max(maxn, i * (n - i));
cout << maxn << endl;
return 0;
}
1406:单词替换¶
提示
这份代码中,有抠单词的操作,用到的是for循环里套了一个while
这种写法,在后续学习算法过程中,是非常重要的代码写法
要好好体会,这个代码思想
另外,在循环内部的最后一行,有一句 i = j - 1;,这句话忘写,会影响答案。你分析分析
代码
#include <bits/stdc++.h>
using namespace std;
string s, a, b;
int main() {
getline(cin, s);
cin >> a >> b;
for (int i = 0, len = s.size(); i < len; i++) {
string temp;
int j = i;
while (j < len && s[j] != ' ') temp += s[j++];
if (temp == a) cout << b << ' ';
else cout << temp << ' ';
// 多余的空格
while (j < len && s[j] == ' ') j++;
i = j - 1;
}
return 0;
}
1407:笨小猴¶
代码
#include <bits/stdc++.h>
using namespace std;
int cnt[30];
bool is_prime(int x) {
if (x < 2) return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0) return false;
return true;
}
int main() {
string s;
cin >> s;
for (int i = 0, len = s.size(); i < len; i++)
cnt[s[i] - 'a']++;
int maxn = -1, minn = 110;
for (int i = 0; i < 26; i++) {
if (cnt[i]) {
maxn = max(maxn, cnt[i]);
minn = min(minn, cnt[i]);
}
}
if (is_prime(maxn - minn)) {
cout << "Lucky Word" << endl;
cout << maxn - minn << endl;
} else {
cout << "No Answer" << endl;
cout << 0 << endl;
}
return 0;
}
1408:系数回文数的个数¶
代码
#include <bits/stdc++.h>
using namespace std;
int primes[1010], idx;
bool st[1010];
void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[idx++] = i;
for (int j = 0; primes[j] <= n / i; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
bool is_panlindrome(int x) {
int ori = x;
int t = 0;
while (x) {
t = t * 10 + x % 10;
x /= 10;
}
if (t == ori) return true;
return false;
}
int main() {
int n;
cin >> n;
get_primes(n);
int cnt = 0;
for (int i = 4; i < idx; i++)
if (is_panlindrome(primes[i])) {
//cout << primes[i] << endl;
cnt++;
}
cout << cnt << endl;
return 0;
}
1409:判决素数个数¶
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], idx;
bool st[N];
void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[idx++] = i;
for (int j = 0; primes[j] <= n / i; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int main() {
get_primes(N);
int x, y;
cin >> x >> y;
int a = lower_bound(primes, primes + idx, x) - primes;
int b = upper_bound(primes, primes + idx, y) - primes - 1;
//cout << a << ' ' << b << endl;
cout << b - a + 1 << endl;
return 0;
}
1410:最大质因子序列¶
代码
#include <bits/stdc++.h>
using namespace std;
bool is_prime(int x) {
if (x < 2) return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0) return false;
return true;
}
int solve(int x) {
for (int i = x; i >= 2; i--) {
if (x % i == 0 && is_prime(i))
return i;
}
}
int main() {
int x, y;
cin >> x >> y;
bool flag = false;
for (int i = x; i <= y; i++) {
if (flag) cout << ',';
cout << solve(i) ;
flag = true;
}
}
1411:区间内的真素数¶
代码
#include <bits/stdc++.h>
using namespace std;
int solve(int x)
{
int t = 0;
while (x)
{
t = t * 10 + x % 10;
x /= 10;
}
return t;
}
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0) return false;
return true;
}
int main()
{
int x, y;
cin >> x >> y;
bool flag = false;
for (int i = x; i <= y; i++)
{
int t = solve(i);
if (is_prime(i) && is_prime(t))
{
if (flag) cout << ',';
cout << i;
flag = true;
}
}
if (!flag) cout << "No";
puts("");
return 0;
}
代码02
// 这份代码,是把质数先筛出来,维护到st数组里(st, state)
// 然后看自己是不是质数,翻转之后的数是不是质数
#include<bits/stdc++.h>
using namespace std;
int m, n, primes[50050], cnt;
bool st[100100], f[100100];
void get_primes() {
for(int i = 2; i <= 100000; i++) {
if(st[i]) continue;
primes[cnt++] = i;
f[i] = true;
for(int j = i + i; j <= 100000; j += i) {
st[j] = true;
}
}
}
int change(int n) {
int x = 0;
while(n) {
x = x * 10 + n % 10;
n /= 10;
}
return x;
}
int main() {
cin >> m >> n;
bool flag = false;
get_primes();
for(int i = m; i <= n; i++) {
if(f[i] && f[change(i)]) {
if(flag) cout << ',';
cout << i;
flag = true;
}
}
if(!flag) cout << "No";
return 0;
}
1412:二进制分类¶
代码
#include<iostream>
using namespace std;
int A, B;
int main() {
for(int i = 1; i <= 1000; i++) {
int zero = 0, one = 0;
int j = i;
while (j) {
if (j % 2 == 1) one++;
else zero++;
j /= 2;
}
//printf("---%d %d %d\n", i, one, zero);
if (one > zero) A++;
else B++;
}
cout << A << ' ' << B << '\n';
return 0;
}
代码02
// 这份代码,用的是二进制的思想,需要对二进制有深入理解
#include <bits/stdc++.h>
using namespace std;
bool check(int x) {
int sum = 0;
int one = 0;
for (int j = 0; (1 << j) <= x; j++) {
if (x & (1 << j)) one++;
sum++;
}
if (one > (sum - one)) return true;
return false;
}
int main() {
int A = 0, B = 0;
for (int i = 1; i <= 1000; i++) {
if (check(i)) A++;
else B++;
}
cout << A << ' ' << B << endl;
return 0;
}
1413:确定进制¶
提示
这个题目,看起来没有什么头绪
要找最小的进制,就从最小的二进制开始枚举吧
如果这个进制成立,那就找到答案了
代码
#include <bits/stdc++.h>
using namespace std;
int work(int x, int y) {
int sum = 0;
int t = 1;
do {
if (x % 10 >= y) return -1;
sum += t * (x % 10);
t *= y;
x /= 10;
} while (x);
return sum;
}
int main() {
int p, q, r;
cin >> p >> q >> r;
bool flag = false;
for (int i = 2; i <= 40; i++) {
int pp = work(p, i);
int qq = work(q, i);
int rr = work(r, i);
if (pp == -1 || qq == -1 || rr == -1) continue;
if (pp * qq == rr) {
cout << i << endl;
flag = true;
break;
}
}
if (!flag) cout << 0 << endl;
return 0;
}
第二节 递归算法¶
1158:求 1+2+3+…¶
提示
问题的边界
求解子问题
代码
1159:斐波那契数列¶
代码
1160:倒数数¶
代码
1161:转进制¶
代码
1162:字符串逆序¶
代码
1163:阿克曼 (Ackermann) 函数¶
代码
1164:digit 函数¶
代码
1165:Hermite 多项式¶
提示
少了条件,保留小数点后2位