回文括号序列计数
链接:https://ac.nowcoder.com/acm/contest/9986/A
来源:牛客网
题目描述
我们定义一个字符串S是回文的,表示S的左右反转和S相同。
我们定义一个字符串是括号序列:
- 空串是括号序列。
- 两个括号序列P和Q的拼接是括号序列。
- 如果P是括号序列,’(’+P+’)'是括号序列。
求长度为 n (0<=n<=10^9) 的回文括号序列的方案数,对 998244353 取膜。
输入描述:
第一行一个 T 表示数据组数。T<=1000000。
接下来 T 行,每行一个 n 。
输出描述:
T 行。对于每组数据,你的答案。
示例1
输入
复制
2
0
1
输出
复制
1
0
脑筋急转弯,既要回文又要是括号串,所以除了空串是1,剩下的都是0
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
//#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <set>
using namespace std;
//using namespace __gnu_cxx;
#define pair(a, b) make_pair(a, b)
#define memset(a, b) memset(a, b, sizeof a)
#define max(a, b) ((a) < (b) ? (b) : (a))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define all(x) x.begin(), x.end()
#define fi first
#define se second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N = 2e5 + 10;
const int M = 4e5 + 10;
const int Mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int _inf = 0xcfcfcfcf;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int P = 13331;
const double eps = 1e-9;
const double PI = acos(-1.0);
int n, m, k;
int main()
{
int T;
cin >> T;
while (T --)
{
cin >> n;
if (n == 0) cout << 1 << endl;
else cout << 0 << endl;
}
return 0;
}
系数
链接:https://ac.nowcoder.com/acm/contest/9986/B
来源:牛客网
题目描述
给定一个多项式 f(x)=(x2+x+1)nf(x)=(x
2
+x+1)
n
,求它的第 k 项系数。
输入描述:
第一行,输入 T ,表示数据组数。
接下来 T 行,每行输入 n 和 k 。
输出描述:
对于每组询问,输出系数模 3 后的结果。
示例1
输入
复制
5
2 0
7 4
4 5
5 3
8 15
输出
复制
1
2
1
0
2
备注:
T<=10000
0\le n\le 10^{15},0\le k\le 2n0≤n≤10
15
,0≤k≤2n
因为是对3取余数,所以就是减2和加1没有区别,所以可以那样化简
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 M = 3 * N;
const int mod = 3;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int qmi(int a, int k)
{
int res = 1 % mod;
while (k)
{
if (k & 1) res = res % mod * a % mod;
a = a % mod * a % mod;
k >>= 1;
}
return res % mod;
}
int C(int a, int b)
{
if (b > a) return 0ll;
int res = 1;
for (int i = 1, j = a; i <= b; i ++, j -- )
{
res = res % mod * j % mod;
res = res % mod * qmi(i, mod - 2) % mod;
}
return res % mod;
}
int lucas(int a, int b)
{
if (a < mod && b < mod) return C(a, b) % mod;
return C(a % mod, b % mod) % mod * lucas(a / mod, b / mod) % mod;
}
signed main(){
ios;
int T;
cin >> T;
while(T --){
int n, k;
cin >> n >> k;
int res;
if ((2 * n - k) & 1) res = -1;
else res = 1;
cout << ((lucas(n * 2, k) % mod * res) % mod + mod) % mod << endl;
}
return 0;
}
末三位
链接:https://ac.nowcoder.com/acm/contest/9986/C
来源:牛客网
题目描述
牛牛最近刚学完指数,他理解了22=4,33=272
2
=4,3
3
=27…
但是,他现在想知道:5^n的末三位是多少?
输入描述:
有多组输入数据。
每组数据输入一个数n,表示指数。
输出描述:
输出5^n的末三位。
示例1
输入
复制
1
3
5
输出
复制
005
125
125
备注:
对于100%的数据,0 <= n <= 1e9。
数据组数 t <= 10^6。
一定会出现循环
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 = 1e6 + 10;
const int M = 3 * N;
const int mod = 1000;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int qmi(int a, int b){
int res = 1;
while(b){
if (b & 1) res = res % mod * a % mod;
a = a % mod * a % mod;
b >>= 1;
}
return res;
}
signed main(){
int n;
while(cin >> n){
int ans = qmi(5, n);
printf("%03d\n", ans);
}
return 0;
}
划数
链接:https://ac.nowcoder.com/acm/contest/9986/D
来源:牛客网
题目描述
一个智能机器人在黑板上写了n个数,它每次划去任意两个数,并在数列的后面写上这两个数的和对11取模的值。
例:5 6 7 8 9,划去5 6后,数列变为7 8 9 0.
有趣的是,机器人在还剩下两个数的时候突然“罢工”了,已知其中一个数cnt(cnt >= 11),求另外一个数的值。
输入描述:
多组测试数据,以 EOF 结尾。
每组数据,第一行输入n和cnt。
第二行输入n个数,第i个数表示num[i]。
输出描述:
每组数据,输出另外一个数的值。
示例1
输入
复制
6 11
6 7 8 9 10 11
输出
复制
7
备注:
2 <= n <= 150000, 1 <= num[i] <= 1e6.
数据组数 t <= 10,保证数据合法。
要特别的注意的是n为2的情况,这样的话另外的数也有可能是大于等于11的
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 = 1e6 + 10;
const int M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int a[N];
signed main(){
int n, cnt;
while(scanf("%lld", &n) != EOF){
cin >> cnt;
bool flag = false;
int sum = 0;
for (int i = 1; i <= n; i ++){
cin >> a[i];
// cout << "--" << endl;
}
if (n == 2){
for (int i = 1; i <= 2; i ++){
if (!flag && a[i] == cnt){
flag = true;
continue;
}
sum = a[i];
}
}
else{
for (int i = 1; i <= n; i ++){
if (!flag && a[i] == cnt){
flag = true;
continue;
}
sum += a[i];
sum %= 11ll;
}
}
cout << sum << endl;
}
return 0;
}
网格
链接:https://ac.nowcoder.com/acm/contest/9986/E
来源:牛客网
题目描述
有一个 n 行 m 列的网格,第 i 行 j 列上有数字 a_{i,j}a
i,j
。每个位置需要从上下左右四个方向中选择互相垂直的两个。
定义 w(x)=x+popcnt(x) ,其中 popcnt(x) 表示 x 的二进制位中 1 的位的数量。
如果两个相邻的位置 (x_1,y_1),(x_2,y_2)(x
1
,y
1
),(x
2
,y
2
) 互相位于对方选择的某个方向上,则对答案由 w(a_{x_1,y_1}\ xor\ a_{x_2,y_2})w(a
x
1
,y
1
xor a
x
2
,y
2
) 的贡献,其中 xor 表示二进制中的按位异或。
小 Z 想问你答案的最大值是多少。
输入描述:
第一行,输入 n,m 。
接下来 n 行 m 列,输入这个网格。
输出描述:
输出答案的最大值。
示例1
输入
复制
3 3
1 3 6
3 2 4
7 4 0
输出
复制
38
备注:
对于 100% 的数据,1\le n,m\le 1000,0\le a_{i,j}<10241≤n,m≤1000,0≤a
i,j
<1024 。
每个位置可以选择两个相互垂直的,也就是说每个位置就是左右两边选一个,上下两个位置,所以这样的话,就是左右和上下是单独分开的,所以先枚举每一行,看当前这一行的每个位置选的左边还是右边,如果状态是0的话表示当前的这个选的是左边,如果状态是1的话就表示当前的这个选的是右边,然后每个状态都可以从前面的两个状态转移,然后再枚举列即可
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 = 1200 + 10;
const int M = N * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int n, m;
int f[N][N][3];
int a[N][N];
int calc(int x){
int ans = x;
while(x){
if (x & 1) ans ++;
x >>= 1;
}
return ans;
}
signed main(){
ios;
cin >> n >> m;
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= m; j ++){
cin >> a[i][j];
}
}
int ans = 0;
for (int i = 1; i <= n; i ++){
for (int j = 2; j <= m; j ++){
f[i][j][0] = max(f[i][j][0], f[i][j - 1][1] + calc(a[i][j] ^ a[i][j - 1]));
f[i][j][1] = max(f[i][j - 1][0], f[i][j - 1][1]);
}
ans += max(f[i][m][0], f[i][m][1]);
}
memset(f, 0, sizeof f);
for (int i = 1; i <= m; i ++){
for (int j = 2; j <= n; j ++){
f[j][i][0] = max(f[j][i][0], f[j - 1][i][1] + calc(a[j][i] ^ a[j - 1][i]));
f[j][i][1] = max(f[j - 1][i][0], f[j - 1][i][1]);
}
ans += max(f[n][i][0], f[n][i][1]);
}
cout << ans << endl;
return 0;
}
组合数问题
链接:https://ac.nowcoder.com/acm/contest/9986/F
来源:牛客网
题目描述
小 M 很喜欢组合数。
小 Z 给了她一个数 n (n为偶数),让她计算 \binom{n}{0}+\binom{n}{2}+\binom{n}{4}…+\binom{n}{n}(
0
n
)+(
2
n
)+(
4
n
)…+(
n
n
) ,小 M 一下子就秒掉了,觉得题好简单。
因此,小 Z 给了她一个难题:给定一个数 n (n 是4的倍数),计算 \binom{n}{0}+\binom{n}{4}+\binom{n}{8}+…+\binom{n}{n}(
0
n
)+(
4
n
)+(
8
n
)+…+(
n
n
) ,答案对 998244353 取模。
小 M 不会做,请你来帮帮她吧!
输入描述:
输入一个数 n 。
输出描述:
输出答案对 998244353 取模的值。
示例1
输入
复制
12
输出
复制
992
备注:
对于所有的数据,1\le n\le 10^{18}1≤n≤10
18
。
首先要知道简单的怎么算,然后类比求出复杂的,求简单的话我们首先用二次项定理化简,然后把奇数项消去,这样的话我们可以拼凑出来,然后求复杂的话我们还需要把2的奇数倍消去,把奇数项消去利用的是-1的奇数次是-1,消除那个我们可以利用i的2次方是-1,就可以消去
机器人
链接:https://ac.nowcoder.com/acm/contest/9986/G
来源:牛客网
题目描述
有 n 个机器人,每个机器人会读入一个 x ,并返回 ax+b 。
现在银临姐姐手里有一个数 x ,她想将机器人按某种顺序排列,使得最终返回得到的 x 尽可能大。
但是计算量太大啦,请你编个程序帮帮她吧。
输入描述:
第一行读入 n,x ,接下来 n 行依次输入 a_i, b_ia
i
,b
i
。
输出描述:
输出最大值。
示例1
输入
复制
2 2
11 4
5 14
输出
复制
268
备注:
对于所有的数据,1\le n,x,a_i,b_i\le 201≤n,x,a
i
,b
i
≤20 。
数据范围这么小,可以考率状态压缩DP,所有的状态满的时候就是所有组的a和b都用到了,一开始是0,都没用到,然后dfs动态规划即可。第二个方法是贪心,假如现在只有两个,分别表示出a先用和b先用的值,然后求这个不等式,如果可以消去x,就能把这个贪心出来
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 = 50;
const int M = 3 * N;
const int mod = 3;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int a[N], b[N];
__int128 f[(1 << 20) + 100];
int n, x;
INT dfs(int val){
if (f[val] != 0) return f[val];
for (int i = 0; i < n; i ++){
if ((val >> i) & 1){
int t = val ^ (1 << i);
f[val] = max(f[val], (INT)(dfs(t) * a[i + 1] + b[i + 1]));
}
}
return f[val];
}
signed main(){
ios;
cin >> n >> x;
for (int i = 1; i <= n; i ++){
cin >> a[i] >> b[i];
}
f[0] = x;
print(dfs((1 << n) - 1));
return 0;
}
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
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;
}
动态最小生成树
链接:https://ac.nowcoder.com/acm/contest/9986/H
来源:牛客网
题目描述
小 Z 喜欢最小生成树。
小 Z 有一张 nn 个点 mm 条边的图,每条边连接点 u_i,v_iu
i
,v
i
,边权为 w_iw
i
。他想进行 qq 次操作,有如下两种类型:
修改第 xx 条边为连接点 y,zy,z ,边权为 tt ;
查询只用编号在 [l,r][l,r] 范围内的边,得到的最小生成树权值是多少。
由于修改和查询量实在是太大了,小 Z 想请你用程序帮他实现一下。
输入描述:
第一行,输入 n,m,q 。
接下来 m 行,输入 u_i,v_i,w_iu
i
,v
i
,w
i
。
接下来 q 行,读入 opt ,若 opt=1 则继续读入 x,y,z,t ,否则读入 l,r 。
输出描述:
对于每次询问,输出最小生成树权值。如果无解,输出 Impossible 。
示例1
输入
复制
5 5 3
1 2 1
2 3 2
3 4 3
4 5 4
1 5 3
2 1 4
2 2 5
2 1 5
输出
复制
10
12
9
备注:
数据保证:
1\le n\le 200,1\le m\le 30000,1\le q\le 30000,1\le u_i,v_i\le n,1\le w_i\le 1000001≤n≤200,1≤m≤30000,1≤q≤30000,1≤u
i
,v
i
≤n,1≤w
i
≤100000 。
1\le x\le m,1\le y,z\le n,1\le t\le 1000001≤x≤m,1≤y,z≤n,1≤t≤100000 。
涉及区间线段树,然后发现暴力也能过
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 = 2e2 + 10;
const int M = N * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int g[N][N], d[N];
int n, m, q;
bool st[N];
struct Edge{
int a, b, w;
}edge[M];
void prim(){
memset(d, 0x3f, sizeof d);
memset(st, 0, sizeof st);
d[1] = 0;
for (int i = 1; i < n; i ++){
int x = 0;
for (int j = 1; j <= n; j ++){
if (!st[j] && (x == 0 || d[j] < d[x])) x = j;
}
st[x] = true;
for (int j = 1; j <= n; j ++){
if (!st[j]) d[j] = min(d[j], g[x][j]);
}
}
}
signed main(){
ios;
cin >> n >> m >> q;
for (int i = 1; i <= m; i ++){
int a, b, c;
cin >> a >> b >> c;
edge[i] = {a, b, c};
}
for (int i = 1; i <= q; i ++){
int op;
cin >> op;
if (op == 1){
int x, y, z, t;
cin >> x >> y >> z >> t;
edge[x] = {y, z, t};
}
else{
memset(g, 0x3f, sizeof g);
for (int i = 1; i <= n; i ++) g[i][i] = 0;
int l, r;
cin >> l >> r;
if (l > r) swap(l, r);
for (int i = l; i <= r; i ++){
int a = edge[i].a, b = edge[i].b, w = edge[i].w;
g[a][b] = g[b][a] = min(g[a][b], w);
}
prim();
bool flag = false;
int ans = 0;
for (int i = 2; i <= n; i ++){
if (d[i] >= 0x3f3f3f3f3f3f3f3f){
flag = true;
break;
}
else ans += d[i];
}
if (flag) cout << "Impossible" << endl;
else cout << ans << endl;
}
}
return 0;
}
贪吃蛇
链接:https://ac.nowcoder.com/acm/contest/9986/I
来源:牛客网
题目描述
无限增长的贪吃蛇小游戏:
在一个n*m的迷宫中,有一条小蛇,地图中有很多围墙,猥琐的出题者用“#”表示,而可以走的路用“.”表示,小蛇他随机出生在一个点上,出生点表示为“S”,他想抵达的终点表示为“E”,小蛇有一个奇怪的能力,他每走一格便会增长一格,即他走了一格后,他的尾巴不会缩回。
小蛇想知道他怎么到达他想去的地方,请你帮助他。
PS:每格长1米,贪吃蛇规定不能撞墙,不能咬自己的身体。
输入描述:
第一行:输入N,M;
第二行:输入S的坐标Xs,Ys,E的坐标Xe,Ye;
后面的N行:
每行输入M个数,描述每一行的情况。
输出描述:
输出一个数,小蛇到达终点的最短距离(单位:cm),若无法达到,输出-1
示例1
输入
复制
3 3
1 1 3 3
.#.
.#.
…
输出
复制
400
示例2
输入
复制
5 5
1 1 5 5
…###
.#…
.#.#.
.#.#.
…#.
输出
复制
1400
备注:
对于 100% 的数据:1\le n,m\le 1001≤n,m≤100 ,保证起点不是围墙。
bfs模板题
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int n, m;
char s[N][N];
PII ss, tt;
bool st[N][N];
int dist[N][N];
int bfs(int startx, int starty){
queue<PII> q;
memset(dist, 0x3f, sizeof dist);
dist[startx][starty] = 0;
q.push({startx, starty});
st[startx][starty] = true;
while(q.size()){
auto t = q.front();
q.pop();
int x = t.first, y = t.second;
for (int i = 0; i < 4; i ++){
int xx = x + dx[i], yy = y + dy[i];
if (s[xx][yy] == '#') continue;
if (st[xx][yy]) continue;
if (xx < 1 || xx > n || yy < 1 || yy > m) continue;
// cout << xx << "---" << yy << endl;
dist[xx][yy] = dist[x][y] + 1;
st[xx][yy] = true;
// cout << dist[xx][yy] << endl;
if (xx == tt.first && yy == tt.second) return dist[xx][yy] * 100;
q.push({xx, yy});
}
}
return -1;
}
signed main(){
cin >> n >> m;
cin >> ss.first >> ss.second >> tt.first >> tt.second;
for (int i = 1; i <= n; i ++){
scanf("%s", s[i] + 1);
}
//cout << tt.first << "--" << tt.second << endl;
cout << bfs(ss.first, ss.second) << endl;
return 0;
}
天空之城
链接:https://ac.nowcoder.com/acm/contest/9986/J
来源:牛客网
题目描述
天空之城有5个小镇,名字分别为Ada, Aed, Akk, Orz, Apq,他们也有相互的路径长度。
希达早已期盼着天空之城,如今她登上了天空之城,就想走遍天空之城的每一个城市,但是她希望自己走的路的长度越小越好,以节省体力和节约时间。
巴鲁同意了,但由于他是主力(男孩子嘛),需要帮希达计算出走遍所有城市的最短路径长度。
由于天空之城具有魔力,如果希达想再走一次自己之前走过的路,则她可以在这条路上不花费任何时间。
但是天空之城的城市太多了,他实在计算不过来,只得请你来帮帮忙了。
输入描述:
第一行,输入n,q, 表示有n个城市,q条边;
第二行,输入一个名字tmp,表示希达想要从tmp城市开始行走;
接下来q行,每行输入两个名字a,b和一个数字val, 表示a城市与b城市之间的距离为val.(注意可能有重边和自环)
输出描述:
帮助巴鲁计算出最短的路径长度,如果无法走遍所有城市,输出“No!”。
示例1
输入
复制
5 5
Orz
Ada Aed 5
Orz Ada 6
Apq Aed 8
Akk Apq 12
Aed Orz 3
输出
复制
28
说明
Ada->Aed->Orz->Aed->Apq->Akk
备注:
多组输入输出(以EOF结束),保证数据组数不超过 10 。
1 <= n <= 5000, 1 <= q <= 200000, 1 <= val <= 1e9. 每个城市的名字长度不超过10。
保证 \sum q \le 200000∑q≤200000 。
最小生成树
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h>
using namespace std;
//using namespace __gnu_cxx;
#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"
//#define x first
//#define y second
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
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 = 4e5 + 10;
const int M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
struct Edge{
int a, b, w;
bool operator<(const Edge &W)const{
return w < W.w;
}
}edge[N];
map<string, int> mp;
int n, q;
int p[N];
int edx;
void get_edx(string str){
if (!mp[str]) mp[str] = ++ edx;
}
int find(int x){
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
signed main(){
while(cin >> n >> q){
memset(edge, 0, sizeof edge);
mp.clear();
edx = 0;
for (int i = 1; i <= n; i ++) p[i] = i;
string temp;
cin >> temp;
for (int i = 1; i <= q; i ++){
string str1, str2;
int w;
cin >> str1 >> str2;
cin >> w;
get_edx(str1);
get_edx(str2);
edge[i] = {mp[str1], mp[str2], w};
}
sort(edge + 1, edge + 1 + q);
int ans = 0;
int cnt = 0;
for (int i = 1; i <= q; i ++){
int a = edge[i].a, b = edge[i].b, w = edge[i].w;
int pa = find(a), pb = find(b);
if (pa != pb){
ans += w;
p[pa] = pb;
cnt ++;
}
}
if (cnt != n - 1) cout << "No!" << endl;
else cout << ans << endl;
}
return 0;
}