1.优秀的拆分
题意
输入和输出
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
10 = 8 + 2 = 2^3 + 2^1 优秀的拆分
7 = 4 + 2 + 1 = 2^2 + 2^1 + 2^0 不优秀的拆分,因为2^0=1不是2的正整数次幂
1.定义变量n, m = 2
2.输入n
3. 如果n是奇数,就说明最后一定会有2^0,所以输出-1,return 0;
4. 只要m小于n, 重复做:
a. 将2累乘并赋值给m
5. 如果m大于n , 就m除等于2
6. 只要n不为0, 重复做:
a. 输出m
b. 拿n减去m再赋值给自身
c. 只要m>n, do:
c-1. m除等于2
*/
int main() {
ios::sync_with_stdio(false);
int n, m = 2;
cin >> n;
if(n % 2) {
cout << -1;
return 0;
}
while(m < n)
m *= 2;
if(m > n)
m /= 2;
while(n) {
cout << m << " ";
n -= m;
while(m > n)
m /= 2;
}
return 0;
}
2.即约分数
题意
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
1/4, 1/8, 7/1 分子和分母的最大公约数是1 => 即约分数

求1到2020之间有多少个即约分数
1. 定义最大公约数函数:gcd(int m, int n), 定义计数器cnt = 0
a. 如果除数等于0,返回被除数 gcd(25,0) => 25
b. 递归调用自身(n, m % n), 被除数变成原来的除数,除数变成m%n的结果
2. for i=1 to 2020, 重复做:
for j=1 to 2020, 重复做:
a. 如果gcd(i,j)等于1, 就cnt加1
3. 输出cnt
*/
//最大公约数
int gcd(int m, int n) {
if(n == 0)
return m;
return gcd(n, m % n);
}
int main() {
ios::sync_with_stdio(false);
int cnt = 0;
F(i,1,2021) {
F(j,1,2021) {
if(gcd(i,j) == 1)
cnt++;
}
}
cout << cnt;
return 0;
}
3.音节判断
题意
输入输出
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
h e ll o
h:辅音,e:元音, ll:辅音, o元音 => yes
一共四段,每一段都可以由多个字母组成
l a n q i a o
l:辅音 a:元音 nq:辅音 iao:元音
1. 定义字符串s, cnt = 0, flag1 = 1(辅音), flag2 = 1(元音)
2. 输入s
3. 遍历字符串,重复做:
a.如果当前字符是辅音,就cnt+1, 辅音关了,把元音开了
b.如果当前字符是元音,就cnt+1, 元音关了,把辅音开了
4. 如果cnt等于4个音节,就输出yes,否则,输出no
*/
int main() {
ios::sync_with_stdio(false);
string s;
int cnt = 0, flag1 = 1, flag2 = 1;
getline(cin, s);
F(i,0,s.size()) {
if((s[i] != 'a' && s[i] != 'e' && s[i] != 'i' && s[i] != 'o' && s[i] != 'u') && flag1)
{
cnt++;
flag1 = 0;
flag2 = 1;
}
if((s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') && flag2)
{
cnt++;
flag1 = 1;
flag2 = 0;
}
}
if(cnt == 4)
cout << "yes";
else
cout << "no";
return 0;
}
4.机器翻译
题意
输入输出
未ac的代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
软件先从内存中查找这个单词的中文含义
如果内存中有,软件就会用它进行翻译
如果内存中没有,就从外存的词典中查找,然后翻译
并将该单词和意思放入内存,以便后续的查找和翻译
内存中有M个单元,每单元只能存放一个单词和词义
先进先出
1, 定义变量m(内存单元),n(文章长度),数组a,队列q(模拟内存),cnt=0(查询次数)
2. 输入m,n
3. 遍历文章长度,输入a[i]
4. for i=0 to n-1, 重复做:
a. 如果内存中没有a[i]的记录且内存未满
a-1.就将a[i]存到内存中
a-2. cnt加1
b. 如果内存中有a[i]的记录,就continue(跳过)
c. 如果内存中没有a[i]的记录且内存已满
a-1. 把内存最早存的单词清掉
a-2. 内存减1
a-3. 再将a[i]存到内存中
a-4. 内存加1
a-5. cnt加1
5. 输出cnt
*/
const int N = 100860;
int m,n, cnt = 0, nc = 0; //内存单元,文章长度,查询次数
int a[N];
int front=-1, rear=-1; //队头和队尾
int q[N];
void enqueue(int val) {
//1.检查队列是否为空
if(front == -1 && rear == -1) {
front = rear = 0;
q[rear] = val;
}
//2.队列是否已满
else if((rear + 1) % m == front)
return;
else {
rear = (rear + 1) % m;
q[rear] = val;
}
}
void dequeue() {
//1.当队列为空时
if(front==-1 && rear == -1)
return;
//2.当队列只有一个元素时
else if(front == rear) {
front = -1;
rear = -1;
}
//3.队列有多个元素时
else {
front = (front + 1) % m;
}
}
int findX(int x) {
for(int i = 0; i < N; i++) {
if(q[i] == x)
return 1;
}
return 0;
}
int main() {
ios::sync_with_stdio(false);
cin >> m >> n;
F(i,0,n) cin >> a[i];
F(i,0,n) {
if(findX(a[i])==0 && nc < m) {
enqueue(a[i]);//放入到内存
cnt++; //查询次数+1
nc++; //内存加1
} else if(findX(a[i])==0 && nc >= m) {
dequeue(); //从内存中去除记录
nc--; //内存减1
enqueue(a[i]); //放入到内存
nc++; //内存加1
cnt++; //查询次数+1
} else continue;
}
cout << cnt;
return 0;
}
ac代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
int m,n, x, cnt = 0;
vector<int> v;
/*
1.定义变量m,n,x(输入),cnt=0
2. 输入m和n
3. 遍历文章,重复做:
a. 输入x
b. 如果内存中没有该单词, 就将该单词存入到内存中,查询次数加1
c. 如果内存满了,就把最早存入的单词移除
*/
int main() {
ios::sync_with_stdio(false);
cin >> m >> n; //输入内存和文章长度
while(n--) {
cin >> x;
if(find(v.begin(), v.end(), x) == v.end()) {
v.push_back(x);
++cnt;
}
if(v.size() > m)
v.erase(v.begin());
}
cout << cnt << endl;
return 0;
}
ac代码 队列模拟内存
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
int m,n,cnt = 0,x;
const int N = 1005;
bool inqueue[N]; //是否在队列里
queue<int> q; //用队列来模拟内存
/*
1.定义变量m,n,x(输入),cnt=0
2. 输入m和n
3. 遍历文章,重复做3:
a. 输入x
b. 如果内存中没有该单词
b-1就向外存查找,查询次数加1
b-2.将该单词存入到内存中
b-3.标记放入
c. 如果内存满了
c-1.将内存最开始的位置标记未放入
c-2.就把最早存入的单词移除
*/
int main() {
ios::sync_with_stdio(false);
cin >> m >> n; //输入内存和文章长度
F(i,0,n) {
cin >> x;
if(inqueue[x] == false) {
cnt++;
q.push(x);
inqueue[x] = true;
}
if(q.size() > m) {
inqueue[q.front()] = false;
q.pop();
}
}
cout << cnt << endl;
return 0;
}
5. 反倍数
题意
给定三个整数 a, bc,如果一个整数既不是 a 的整数倍也不是 b 的整数倍还不是 c 的整数倍,则这个数称为反倍数。
请问在 1 至 n 中有多少个反倍数。
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
1到30有多少个反倍数, 2, 3, 6
1 5 7 11 13 17 19 23 25 29
cnt = 10

1.定义变量cnt=0, a, b, c, n
2. 输入n,a,b,c
2. for i=1 to n, do:
a. 如果i不是a、b和c的倍数,cnt加1
*/
int main() {
ios::sync_with_stdio(false);
int cnt = 0, a, b, c, n;
cin >> n >> a >> b >> c;
F(i,1,n+1) {
if(i%a && i%b && i%c)
cnt++;
}
cout << cnt;
return 0;
}
6.凯撒密码
题目描述
输入输出
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
单词中的所有字母都后移3位
a变成d
b变成e
z变成c
1. 定义字符串s
2. 输入s
3. 遍历字符串,重复做:
a.如果遇到字符z, 就将字符变成c
b.否则如果遇到字符x,就将字符变成a
c.否则如果遇到字符y,就将字符变成b
d.否则,每个字符都加3
*/
int main() {
ios::sync_with_stdio(false);
string s;
cin >> s;
F(i,0,s.size()) {
if(s[i] == 'z')
s[i] = 'c';
else if(s[i] == 'y')
s[i] = 'b';
else if(s[i] == 'x')
s[i] = 'a';
else
s[i] += 3;
}
cout << s;
return 0;
}
第二种写法
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
单词中的所有字母都后移3位
a变成d
b变成e
z变成c
1. 定义字符串s
2. 输入s
3. 遍历字符串,重复做:
a.如果遇到字符z, 就将字符变成c
b.否则如果遇到字符x,就将字符变成a
c.否则如果遇到字符y,就将字符变成b
d.否则,每个字符都加3
*/
int main() {
ios::sync_with_stdio(false);
string s;
cin >> s;
F(i,0,s.size()) {
if(s[i]>='x' && s[i] <= 'z')
s[i] -= 23;
else
s[i] += 3;
}
cout << s;
return 0;
}
7.约数个数
题目
代码
#include <iostream>
#define pragama GCC optimize(2)
#define F(i,a,b) for(int i = a; i < b; i++)
using namespace std;
const int N = 100;
int a[N] = {0};
/*
16有多少个约数
1*2*3*4 => 1*2*3*2*2 => 2^3 * 3^1
约数:先将一个数字分解成n个质因数,然后将(质数的幂+1)相乘
约数个数 = (3+1)*(1+1) = 8
120有多少个约数
先将120分解成多个质因数: 2*2*2*3*5 => 2^3 * 3^1 * 5^1
约数个数 = (3+1)*(1+1)*(1+1) = 16
1. 定义变量num, res = 1(累乘器,用来累乘质因数的幂加1),数组a
2. 输入num
3. for i=2 to num, do: (分解质因数)
只要i能被num整除,do:
a.下标i对应的数组值加1,表示下标i有多少个数
b. num 等于 num除以i
4. 遍历数组a,do:
如果下标i对应的数组元素不等于0,就将质因数幂+1累乘到res种
5. 输出res
*/
int main()
{
ios::sync_with_stdio(false);
int num = 1200000;
int res = 1;
for(int i = 2; i <= num; i++) {
while(num % i == 0) {
a[i]++;
num /= i;
}
}
F(i,0, 100) {
if(a[i])
res *= a[i] + 1;
// cout << a[i] << " ";
}
cout << res;
return 0;
}
8.阶乘约数
其实就是约数题外边再套一层for循环,i从阶乘的最大数开始,比如求阶乘(100)的约数,i就从100开始,只要i不等于0,迭代条件n=--i
题目
定义阶乘 n! = 1 × 2 × 3 × · · · × n!=1×2×3×⋅⋅⋅×n。
请问 100! (100 的阶乘)有多少个正约数。
代码
#include <iostream>
#define F(i,a,b) for(int i = a; i < b; i++)
#define pragma GCC optimize(2)
#define LL long long
using namespace std;
int factor[100] = {0};
/*
16有多少个约数
1*2*3*4 => 1*2*3*2*2 => 2^3 * 3^1
约数:先将一个数字分解成n个质因数,然后将(质数的幂+1)相乘
约数个数 = (3+1)*(1+1) = 8
120有多少个约数
先将120分解成多个质因数: 2*2*2*3*5 => 2^3 * 3^1 * 5^1
约数个数 = (3+1)*(1+1)*(1+1) = 16
1. 定义变量num, res = 1(累乘器,用来累乘质因数的幂加1),数组a
2. 输入num
3. for i=num; 只要i不等于0, n=--i, do:
4. for =2 to num, do: (分解质因数)
只要j能被num整除,do:
a.下标j对应的数组值加1,表示下标j有多少个数
b. num 等于 num除以i
4. 遍历数组a,do:
如果下标i对应的数组元素不等于0,就将质因数幂+1累乘到res中
5. 输出res
*/
LL findFactor(int n) {
LL res = 1; //累乘器
//从n开始
for(int i = n; i; n = --i) {
for(int j = 2; j <= n; j++) {
//只要n%k等于0
while(n % j == 0) {
factor[j]++;
n /= j;
}
}
}
F(i,0,100) {
if(factor[i])
res *= factor[i] + 1;
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cout << findFactor(100);
return 0;
}
9.斐波那契数列最大公约数
fib(gcd(m,n))
题目
斐波那契数列最大公约数
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <cmath>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
求斐波那契数列的最大公约数 gcd
1. 定义最大公约数函数gcd(int m, int n)
a. 如果除数n等于0,就返回被除数m
b. 否则(n不为0),返回gcd(n, m % n),
被除数不断变成小的除数,除数变成被除数%除数
2. 定义fib函数(int n)
a. 定义变量p用来先记录,后返回,定义数组a, a[1]=1,a[2]=1
b. 如果a[n]不等于0,就返回a[n] //查找到有,直接返回
c. 将递归公式fib(n-1)+fib(n-2)赋值给p
d. 将p的值赋值给a[n]
e. 返回p
3. 定义变量n,m
4. 输出fib(gcd(n,m)) 将gcd函数套到fib函数里,这就是fib数列的最大公约数
*/
const int N = 1000000;
int a[N];
int gcd(int a, int b) {
if(a % b)
return gcd(b, a % b);
else return b;
}
LL fib(int n) {
LL p;
a[1] = a[2] = 1;
if(a[n] != 0)
return a[n]; //查找到有,直接返回
p = fib(n - 1) + fib(n - 2);
a[n] = p; //先记录后返回
return p;
}
int main() {
ios::sync_with_stdio(false);
cout << fib(gcd(2020,520));
return 0;
}
10. 长草(多源bfs)
题目
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
// 2~1000
/*
小数点.为空地,g表示长了草
草会往上下左右四个方向长,原来的空地会变成草
输出k个月后的图
多源bfs,多个起点,把g入队
1. 定义笛卡尔坐标dx和dy,存放地图的二维字符数组g,二维数组vis表示标记访问过的点
n,m,k(n行m列k个月), 坐标结构体node{a,b,step}, 存放坐标的队列q
2. 输入n,m
3. 遍历二维地图,输入二维数组
4. 输入k
5. 定义bfs函数()
a.枚举二维地图,如果是草g(有多个草的坐标要入队列,所以需要遍历整张图)
a-1. 就加入队列
a-2. 标记访问过了
b. 只要队列不为空,do:
b-1. 取队首元素赋值给结构体坐标变量tmp
b-2. 弹出队首元素
b-3. 如果到了k个月,就退出(根据step来判断)
b-4. 遍历起点的上下左右四个方向,do:
c-1. 新坐标(xx,yy)等于各自的起点坐标加上移动的距离
c-2. 过滤掉坐标越界的情况
c-3. 如果草g的新坐标(xx,yy)是原来的空地.
c-3-1. 就将原来的空地变成草地g
c-3-2. 将新坐标入队,步长+1
c-3-2. 标记访问过了
6. 调用bfs函数
7. 遍历二维地图,输出二维数组
*/
const int N = 1005;
//上下左右
int dx[] = {0,0,-1,1};
int dy[] = {1,-1,0,0};
int n,m,k; //n行m列,k个月
char g[N][N];//存放地图
int vis[N][N] = {0}; //标记访问过的点
//坐标
struct node {
int a, b, step;
};
queue<node> q;
void bfs() {
//枚举,如果是g,就加入队列
F(i,1,n+1) {
F(j,1,m+1) {
if(g[i][j] == 'g') {
q.push({i,j,0});
vis[i][j] = 1;
}
}
}
//只要队列不为空
while(q.size()) {
node tmp = q.front();
q.pop();
if(tmp.step == k)
return;
for(int i = 0; i < 4; i++) {
int xx = dx[i] + tmp.a;
int yy = dy[i] + tmp.b;
//过滤掉坐标越界的情况
if(xx<1 || xx>n || yy<1 || yy>m)
continue;
//将g的上下左右都变成g
if(g[xx][yy] == '.') {
g[xx][yy] = 'g';
q.push({xx,yy,tmp.step+1});
vis[xx][yy] = 1;
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
F(i,1,n+1) {
F(j,1,m+1) {
cin >> g[i][j];
}
}
cin >> k;
bfs();
F(i,1,n+1) {
F(j,1,m+1) {
cout << g[i][j];
}
cout << endl;
}
return 0;
}
11. 数字9
题目
1到2019有多少个数位中包含9,1999虽然有3个9,但只算一个数位中包含9
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <sstream>
#include <string>
#include <string.h>
#include <cstring>
#include <vector>
#define F(i,a,b) for(int i = a; i < b; i++)
#define LL long long
#pragma GCC optimize(2)
using namespace std;
/*
1~2019有多少个数位中包含数字9
只要包含9,就算一个数,如1999算一个数包含9
9 == 9
9 == 9
9 == 9
1 == 9
方法
1. 不断拿个位数去与9比较,只要有一个等于9,计算器就+1
*/
int has9(int n) {
//955
while(n) {
if(n % 10 == 9) {
return 1;
}
n /= 10;
}
return 0;
}
LL cnt9(int x, int n) {
LL cnt = 0;
for(int i = x; x <= n; x++) {
if(has9(x))
cnt++;
}
return cnt;
}
int main() {
ios::sync_with_stdio(false);
cout << cnt9(1,2019);
return 0;
}