1.3n +-1
题目描述
给定一个整数n,只能对n进行以下这几种操作:
1.若n是3的倍数除以3
2.加1
3.减1
求最少多少次操作才能使n变为1?
输入
一行一个整数n
输出
一行一个整数表示答案
样例输入
4
样例输出
2
提示
对于样例1:4-1=3,3/3=1
对于60%的数据 0<=n<=10^9
对于100%的数据0<=n<=10^18
思路:
首先优先级肯定能除以3,先除以3.
其次进行减1或者加1,凑3的倍数
以此类推重复操作
注意:当n=0、1、2时,需要特殊处理,结果直接输出1
#
2.邻而不同
题目描述
有 N 个人,从 1 到 N 编号,站成一圈。1 号的右边是 2 号,2号的右边是 3 号,……,N 号的右边是 1 号。
我们要给每个人一个 0 到 M−1 之间的整数(包括 0 和 M−1)。做这件事有 M^N 种方式,其中有多少种方式满足相邻的两个人的数不同。输出此数目除以 998244353 的余数。
数据范围
2≤N,M≤10^6
N 和 M 是整数。
输入
N M
输出
输出答案。
样例输入
3 3
样例输出
6
提示
样例输入 2
4 2
样例输出 2
2
样例输入 3
987654 456789
样例输出 3
778634319
思路:
#include<iostream>
using namespace std;
long long int n,m;
long long int modnum = 998244353;
long long int pw(long long int a,long long int b){
long long int nw=a, ans=1;
while(b){
if(b & 1ll){
ans *= nw;
ans %= modnum;
}
b >>= 1;
nw *= nw;
nw %= modnum;
}
return ans;
}
int main(){
cin >> n >> m;
cout << (pw (m - 1, n) + ((n & 1ll) ? (1 - m):(m - 1)) + modnum) % modnum << endl;
return 0;
}
3.代金券
题目描述
你到商店,要买 N 个东西。第 i 个东西的价格是 Pi 元。
你有 M 张代金券。第 i 张代金券可以用在一个价格不低于 Li 元的东西上,用了这张代金券可以获得 Di 元优惠。
每张代金券只能用一次。不能把多张代金券用在同一个东西上。
要买 N 个东西,至少要花多少钱?
数据范围
1≤N,M≤2×10^5
1≤Pi≤10^9
1≤Di≤Li≤10^9
输入的值都是整数。
输入
N M
输出
输出答案。
样例输入
3 3
4 3 1
4 4 2
2 3 1
样例输出
4
提示
样例2
输入
10 5 9 7 1 5 2 2 5 5 7 6 7 2 7 8 2 3 2 4 1 2
输出
37
思路:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
int p[maxn];
multiset<int> ms;
multiset<int>:: iterator it;
struct node {
int l, d;
} vouchers[maxn];
bool cmp(node a, node b) {
if (a.d != b.d) {
return a.d > b.d;
}
return a.l < b.l;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
long long sum = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &p[i]);
ms.insert(p[i]);
sum += p[i];
}
for (int i = 0; i < m; i++) {
scanf("%d", &vouchers[i].l);
}
for (int i = 0; i < m; i++) {
scanf("%d", &vouchers[i].d);
}
sort(p, p + n, greater<int>());
sort(vouchers, vouchers + m, cmp);
int j = 0;
for (int i = 0; i < m; i++) {
it= ms.lower_bound(vouchers[i].l);
if (it != ms.end()) {
sum -= vouchers[i].d;
ms.erase(it);
}
}
printf("%lld\n", sum);
return 0;
}
4.疫情
题目描述
疫情期间,居民被封锁在家中,一栋楼居民楼可以视作尺寸为n行n列的矩阵,矩阵的每个位置为一个房间,房间里可能住人,也可能空着。在第一天,有些房间里的人感染了病毒,以后每天,感染病毒的人会使其邻居感染病毒,(已经得病的不变),空房间不会传染。请输出第m天感染病毒的人数。
输入
第一行只有一个整数n,表示尺寸
接下来为n行n列的矩阵,
矩阵中 '.'表示未感染的人
'#'表示空房间
'@'表示感染病毒的人
最后一行是一个整数m
输出
输出第m天,感染的人数。
样例输入
5
....#
.#.@.
.#@..
#....
.....
4
样例输出
16
提示
1<=n,m<=100
思路:搜索
#include <iostream>
using namespace std;
int f[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
char map[110][110];
int main(){
int n, m;
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cin >> map[i][j];
}
}
cin >> m;
while(--m){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(map[i][j] != '@')continue;//未感染跳过
for(int k = 0; k < 4; k++){//四个方向进行传染
int x = i + f[k][0];
int y = j + f[k][1];
if(map[x][y] == '.'){
// cout << x<<"---" << y<<"+++"<<endl;
map[x][y] = '*';//当前天刚感染 避免更新当前天感染的人再传染
}
}
}
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(map[i][j] == '*')
map[i][j] = '@';// 标记回来,不会对下次产生影响
}
}
}
int cnt = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(map[i][j] == '@')
cnt++;
}
}
cout << cnt << endl;
return 0;
}