A. 回文括号序列计数
1.题意
求长度为n的括号序列的方案数。
2.思路
核心:读懂题目
80%的人认为“()”是回文括号序列。
首先要是括号序列,那么n必须为偶数,并且括号形式要么是()()一组接着一组,要么是(())套娃形式,但这两种都符合回文的定义。
所以除了n=0时为1,n为其他数结果都是0.
3.代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t, n;cin >> t;
while(t--)
{
cin>>n;
cout << !n << endl;
}
return 0;
}
C. 末三位
1.题意
求5^n末三位
2.思路
方法1:求循环节
方法2:快速幂
3.代码
#include<iostream>
using namespace std;
typedef long long LL;
LL qp(LL a, LL b){
LL res = 1;
while(b){
if(b & 1) res = res * a % 1000;
b >>= 1;
a = a * a % 1000;
}
return res;
}
int main(){
int n;
while(~scanf("%d", &n)) printf("%03d\n",qp(5, n));
return 0;
}
D. 划数
1.题意
求n个数的和对11取模结果
2.思路
首先总和sum%11的值肯定是不变的,如果n=2,不执行操作,那么结果就是sum-cnt。
否则n>2,进行操作,sum%11 = (cnt + ans)%11, ans = (sum - cnt)%11 。
3.代码
#include <iostream>
using namespace std;
typedef long long LL;
int n, cnt, x;
int main(){
while(~scanf("%d%d", &n, &cnt)){
LL sum = 0;
for(int i = 0 ; i < n; ++ i)
cin >> x,sum += x;
sum -= cnt;
if(n == 2) cout << sum << endl;
else cout << sum%11 << endl;
}
return 0;
}
F. 组合数问题
1.题意
2.思路
参考dalao
3.代码
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const ll mod = 998244353;
ll quick_pow(ll a, ll b) {
ll ans = 1;
while (b) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans % mod;
}
void solve() {
ll n; cin >> n;
cout << (((quick_pow(2, n - 2) % mod + quick_pow(-4, n / 4) * quick_pow(2, mod - 2) % mod) % mod + mod) % mod) << endl;
}
signed main() {
solve();
}
G. 机器人
1.题意
给出x和n个ai,bi,求最大值
2.思路
1.状压dp:dp[i]:状态为i的最大值
2.贪心
3.代码
//状压dp
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef __int128 LL;
const int N = 20, M = 1 << N;
int a[N], b[N];
LL f[M];
void print(LL x)
{
vector<int> nums;
while(x) nums.push_back(x % 10), x /= 10;
reverse(nums.begin(), nums.end());
for(int i : nums) printf("%d", i);
}
int main()
{
int n, x;
scanf("%d%d", &n, &x);
for(int i = 0; i < n; i ++) scanf("%d%d", &a[i], &b[i]);
f[0] = x;
for(int i = 1; i < 1 << n; i ++)
{
for(int j = 0; j < n; j ++)
if(i >> j & 1) f[i] = max(f[i], f[i ^ (1 << j)] * a[j] + b[j]);
}
print(f[(1 << n) - 1]);
return 0;
}
//贪心
#include <bits/stdc++.h>
using namespace std;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
typedef __int128 INT;
typedef unsigned long long ULL;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
inline void print(INT x) {
if (x < 0) { putchar('-'); x = -x; }
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
const int N = 110;
const int mod = 998244353;
INT a[N], b[N], temp[N];
INT n, x;
struct Node{
INT a, b;
bool operator<(const Node &W)const{
return (W.a- 1) * b > (a - 1) * W.b;
}
}node[N];
signed main(){
gt(n), gt(x);
for (int i = 1; i <= n; i ++){
gt(node[i].a);
gt(node[i].b);
}
sort(node + 1, node + 1 + n);
INT ans = x;
for (int i = 1; i <= n; i ++){
ans *= (node[i].a);
}
temp[n + 1] = 1;
for (int i = n; i >= 2; i --){
temp[i] = temp[i + 1] * node[i].a;
}
for (int i = 1; i <= n; i ++){
INT res = node[i].b * temp[i + 1];
ans += res;
}
print(ans);
return 0;
}
I. 贪吃蛇
1.题意
走迷宫
2.思路
Flood-Fill模板题
dfs或bfs都可
3.代码
//dfs
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 105;
int Min = 0x3f3f3f3f;
int n, m;
char g[N][N];
bool st[N][N];
int sx,sy, ex, ey;
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
bool check(int x, int y){
if(x > 0 && x <= n && y > 0 && y <= m && g[x][y] == '.' && !st[x][y])
return 1;
return 0;
}
void dfs(int x, int y, int s){
if(x == ex && y == ey){
Min = min(s, Min);
return;
}
for(int i = 0; i < 4; ++ i){
int tx = x + dx[i];
int ty = y + dy[i];
if(check(tx, ty)){
st[tx][ty] = 1;
dfs(tx, ty, s + 1);
st[tx][ty] = 0;
}
}
}
int main(){
cin >> n >> m;
cin >> sx >> sy >> ex >> ey;
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= m; ++ j) cin >> g[i][j];
dfs(sx, sy, 0);
if(Min == 0x3f3f3f3f) puts("-1");
else
cout << Min * 100 << endl;
return 0;
}
//bfs
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 105;
char c[N][N];
int vis[N][N];
int n, m, sx, sy, ex, ey;
struct node
{
int x, y, s;
}st;
int to[4][2]={0,1,0,-1,1,0,-1,0};
void bfs()
{
vis[sx][sy]=1;
queue<node>q;
q.push({sx, sy, 0});
while(q.size())
{
st = q.front();
q.pop();
if(st.x == ex && st.y == ey)
{
cout<< st.s * 100<< endl;
return;
}
for(int i = 0; i < 4; ++ i)
{
int xx = st.x + to[i][0];
int yy = st.y + to[i][1];
if(c[xx][yy] == '.' && !vis[xx][yy] && xx >= 1 && xx <= n && yy >= 1 && yy <= m)
{
q.push({xx, yy, st.s + 1});
vis[xx][yy] = true;
}
}
}
puts("-1");
return ;
}
int main()
{
cin>> n>> m;
cin>> sx>> sy>> ex>> ey;
for(int i = 1; i <= n; ++ i) cin>>c[i] + 1;
bfs();
return 0;
}
J. 天空之城
1.题意
求最小生成树
2.思路
模板题, 把地点用map映射成编号,用kruskal即可
3.代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 5005, M = 200005, INF = 0x3f3f3f3f;
typedef long long LL;
int n, m; // n是点数,m是边数
int p[N]; // 并查集的父节点数组
int c = 0;
map<string, int>mp;
struct Edge // 存储边
{
int a, b, w;
bool operator< (const Edge &W) const
{
return w < W.w;
}
}edges[M];
int find(int x) // 并查集核心操作
{
return x == p[x]?x:p[x] = find(p[x]);
}
void kruskal()
{
sort(edges, edges + m);
for (int i = 1; i <= n; i ++ ) p[i] = i; // 初始化并查集
LL res = 0;
int cnt = 0;
for (int i = 0; i < m; i ++ )
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a), b = find(b);
if (a != b) // 如果两个连通块不连通,则将这两个连通块合并
{
p[a] = b;
res += w;
cnt ++ ;
}
}
if (cnt < n - 1) puts("No!");
else cout << res << endl;
}
int main(){
while(cin >> n >> m){
c = 0;
mp.clear();
string a, b;
cin >> a;
for(int i = 0; i < m; ++ i){
int x;
cin >> a >> b >> x;
if(!mp[a]) mp[a] = ++c;
if(!mp[b]) mp[b] = ++c;
edges[i] = {mp[a], mp[b], x};
}
kruskal();
}
return 0;
}