素数回文
链接:https://ac.nowcoder.com/acm/contest/11571/H
来源:牛客网
题目描述
现在给出一个素数,这个素数满足两点:
1、 只由1-9组成,并且每个数只出现一次,如13,23,1289。
2、 位数从高到低为递减或递增,如2459,87631。
请你判断一下,这个素数的回文数是否为素数(13的回文数是131,127的回文数是12721)。
输入描述:
输入只有1行。
第1行输入一个整数t,保证t为素数。
数据保证:9<t<109
输出描述:
输出一行字符串,如果t的回文数仍是素数,则输出“prime”,否则输出"noprime"。
示例1
输入
复制
13
输出
复制
prime
说明
13的回文数是131,131是素数
示例2
输入
复制
17
输出
复制
noprime
说明
17的回文数是171,171不是素数(因子有3)
备注:
素数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
素数的回文数为题意中的定义,1331不是素数的回文数。
判断一个很大的数是不是质数,当枚举到很大的时候还没有发现除数的话,可以判断这个数就是质数
#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;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#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 out = 0)
{
char c;
while((c=getchar()) < 48 || c > 57);
while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
return out;
}
const int N = 110;
const int M = 2e5 + 10;
const int mod = 77797;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int get_num(string str){
int ans = 0;
for (int i = 0; i < str.size(); i ++){
int x = (str[i] - '0');
ans = ans * 10 + x;
}
return ans;
}
signed main(){
string str1;
cin >> str1;
string str = str1;
for (int i = str1.size() - 2; i >= 0; i --) str += str1[i];
int num = get_num(str);
bool flag = false;
for (int i = 2; i * i <= num; i ++){
if (i >= 1e8) cout << "prime" << endl, flag = true;
if (num % i == 0 ){
flag = true;
cout << "noprime" << endl;
break;
}
}
if (!flag) cout << "prime" << endl;
return 0;
}
追债之旅
链接:https://ac.nowcoder.com/acm/contest/11571/K
来源:牛客网
题目描述
小明现在要追讨一笔债务,已知有n座城市,每个城市都有编号,城市与城市之间存在道路相连(每条道路都是双向的),经过任意一条道路需要支付费用。小明一开始位于编号为1的城市,欠债人位于编号为n的城市。小明每次从一个城市到达另一个城市需要耗时1天,而欠债人每天都会挥霍一定的钱,等到第k天后(即第k+1天)他就会离开城n并再也找不到了。小明必须要在他离开前抓到他(最开始为第0天),同时希望自己的行程花费和欠债人挥霍的钱的总和最小,你能帮他计算一下最小总和吗?
输入描述:
第1行输入三个整数n,m,k,代表城市数量,道路数量和指定天数
第2-m+1行,每行输入三个整数u,v,w,代表起点城市,终点城市和支付费用。(数据保证无重边,自环)
第m+2行输入k个整数,第i个整数ai代表第i天欠债人会挥霍的钱。
数据保证:0<n≤1000,0<m≤10000,0<k≤10,1≤u,v≤n,0<w,ai≤1000
输出描述:
输出一行,一个整数,代表小明的行程花费和欠债人挥霍的钱的最小总和,如果小明不能抓住欠债人(即不能在第k天及之前到达城n),则输出-1。
示例1
输入
复制
3 3 2
1 3 10
1 2 2
2 3 2
3 7
输出
复制
13
说明
小明从1-3,总共费用=10(行程)+3(挥霍费用)=13,是方案中最小的(另一条方案花费14)。
示例2
输入
复制
3 2 1
1 2 3
2 3 3
10
输出
复制
-1
说明
小明无法在第1天赶到城3,所以输出-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;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#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 out = 0)
{
char c;
while((c=getchar()) < 48 || c > 57);
while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
return out;
}
const int N = 2e5 + 10;
const int M = 2e5 + 10;
const int mod = 77797;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int a[N];
int h[N], e[N], w[N], ne[N], idx;
int dist[N][20];
int n, m, k;
bool st[N][20];
void add(int a, int b, int c){
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
}
struct Node{
int id;
int day;
int step;
bool operator<(const Node &W)const{
return step > W.step;
}
};
void dijkstra(){
memset(dist, 0x3f, sizeof dist);
dist[1][0] = 0;
priority_queue<Node> heap;
heap.push({1, 0, 0});
while(heap.size()){
auto t = heap.top();
heap.pop();
int ver = t.id, day = t.day, step = t.step;
if (st[ver][day]) continue;
st[ver][day] = true;
for (int i = h[ver]; ~i; i = ne[i]){
int j = e[i];
int day1 = day + 1;
if (day1 > k) break;
int d = a[day1] + w[i];
//cout << j << " " << day1 << " " << d << endl;
if (dist[j][day1] > dist[ver][day] + d){
dist[j][day1] = dist[ver][day] + d;
heap.push({j, day1, dist[j][day1]});
}
}
}
}
signed main(){
scanf("%lld%lld%lld", &n, &m, &k);
memset(h, -1, sizeof h);
for (int i = 1; i <= m ; i ++){
int a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
add(a, b, c), add(b, a, c);
}
for (int i = 1; i <= k; i ++) scanf("%lld", &a[i]);
dijkstra();
//cout << dist[3][1] << endl;
int ans = 0x3f3f3f3f3f3f3f3f;
for (int i = 1; i <= k; i ++){
ans = min(ans, dist[n][i]);
}
if (ans == 0x3f3f3f3f3f3f3f3f) cout << "-1" << endl;
else cout << ans << endl;
return 0;
}
模拟战役
链接:https://ac.nowcoder.com/acm/contest/11571/G
来源:牛客网
题目描述
齐齐和司机在玩单机游戏《红色警戒IV》,现在他们的游戏地图被划分成一个nm的方格地图。齐齐的基地在最上方的4行格内,司机的基地在最下方的4行格内。他们只有一种攻击方式:远程大炮,相关属性如下:
1、 大炮可以打到地图的任意一个位置。
2、 双方每次必须动用本方的一门大炮攻击,齐齐先手,双方交替进行攻击。
3、 一方大炮只能攻击另一方大炮,不能攻击本方或强制攻击未获得视野的地区。
4、 被一方大炮击中的另一方大炮会产生以攻击点为中心的33的波及区域,波及区域内如果有其他大炮则也会产生33的波及区域。
5、 两方的基地相距很远,所以不存在攻打敌方大炮时波及到本方大炮的情况。
齐齐偷偷开了“间谍卫星”,所以他能看到司机的大炮部署,司机则无视野。但如果齐齐做出攻击,司机会立即获取到发动攻击的大炮的视野,并在回合开始时动用大炮(如果存在的话)将其摧毁(摧毁后可能产生的连锁不计入视野)。
现在给出齐齐和司机的大炮部署,问齐齐在选择最优的策略下,在摧毁所有司机的大炮后可以保留最多几门本方大炮。
输入描述:
第1行输入一个整数m,表示地图的宽度。
第2-5行,每行输入一串长度为m的字符串,代表司机的大炮部署。(大炮为"“号,空地为“.”号)
第6-9行,每行输入一串长度为m的字符串,代表齐齐的大炮部署。(大炮为”"号,空地为“.”号)
数据保证:0<m≤100
输出描述:
输出一行,一个整数。代表摧毁所有司机的大炮后最多保留几门大炮。如果不能摧毁所有司机的大炮,则输出-1。
示例1
输入
复制
3
…
..
…*
…
…
.
…
.
输出
复制
4
示例2
输入
复制
3
…
…
…
…
…
…
.*.
…
输出
复制
-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;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#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 out = 0)
{
char c;
while((c=getchar()) < 48 || c > 57);
while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
return out;
}
const int N = 110;
const int M = 2e5 + 10;
const int mod = 77797;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int m;
char s[10][N];
int idx;
bool st[N][N];
int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
vector<int> v;
int bfs(int x, int y, int shang, int xia){
queue<PII> q;
q.push({x, y});
st[x][y] = true;
int cnt = 1;
while(q.size()){
auto t = q.front();
q.pop();
int x = t.first, y = t.second;
for (int i = 0; i < 8; i ++){
int xx = x + dx[i];
int yy = y + dy[i];
if (st[xx][yy]) continue;
st[xx][yy] = true;
if (xx < xia || xx > shang || yy < 1 || yy > m) continue;
if (s[xx][yy] == '*'){
// cout << xx << " " << yy << endl;
//st[xx][yy] = true;
q.push({xx, yy});
//v.push_back({xx, yy});
cnt ++;
}
}
}
// cout << cnt << "---" << endl;
return cnt;
}
signed main(){
scanf("%lld", &m);
for (int i = 1; i <= 8; i ++) scanf("%s", s[i] + 1);
int cnt = 0;
for (int i = 1; i <= 4; i ++){
for (int j = 1; j <= m; j ++){
if (s[i][j] == '*' && !st[i][j]){
bfs(i, j, 4, 1);
cnt ++;
}
}
}
// cout << "cnt: "<<cnt << endl;
int ans = 0;
for (int i = 5; i <= 8; i ++){
for (int j = 1; j <= m; j ++){
if (s[i][j] == '*') ans ++;
if (s[i][j] == '*' && !st[i][j]){
// idx ++;
int temp = bfs(i, j, 8, 5);
v.push_back(temp);
}
}
}
sort(v.begin(), v.end());
//cout << cnt << endl;
//cout << ans << endl;
if (v.size() >= cnt){
int tem = 0;
for (int i = 0; i < cnt - 1; i ++) tem += v[i];
cout << ans - tem << endl;
}
else cout << "-1" << endl;
return 0;
}
最短路径
链接:https://ac.nowcoder.com/acm/contest/11571/F
来源:牛客网
题目描述
现在给出一幅有向图(有重边,无自环),问你多少组点对满足他们之间的最短路=d,输出点对的个数。
输入描述:
第1行输入三个整数n,m,d,表示图的点数,边数和查询的值。
第2-m+1行,每行输入三个整数s,t,v,表示边的起点,终点和边权。
数据保证:0<n≤50,0<m≤5000,0<d≤5000,0<s,t≤n,0<v≤100。
输出描述:
输出一行,一个整数表示满足条件的点对个数。
示例1
输入
复制
2 2 1
1 2 1
2 1 2
输出
复制
1
说明
只有1到2的最短路是1,所以只有1个。
示例2
输入
复制
2 2 1
1 2 1
2 1 1
输出
复制
2
说明
1到2和2到1的最短路都是1,所以有2个。
备注:
(s,t)和(t,s)是两组不同的点对。
模板题
#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;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#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 out = 0)
{
char c;
while((c=getchar()) < 48 || c > 57);
while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
return out;
}
const int N = 1010;
const int M = 2e5 + 10;
const int mod = 77797;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
int g[N][N];
int n, m, d;
signed main(){
scanf("%lld%lld%lld", &n, &m, &d);
memset(g, 0x3f, sizeof g);
for (int i = 1; i <= m; i ++){
int a, b, c;
gt(a), gt(b), gt(c);
g[a][b] = c;
// g[b][a] = c;
}
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= n; j ++){
for (int k = 1; k <= n; k ++){
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
}
}
int ans = 0;
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= n; j ++){
if (g[i][j] == d) ans ++;
}
}
cout << ans<< endl;
return 0;
}
奇♂妙拆分
链接:https://ac.nowcoder.com/acm/contest/11571/E
来源:牛客网
题目描述
在遥远的米♂奇♂妙♂妙♂屋里住着一群自然数,他们没事就喜欢拆♂开自己来探♂究。现在他们想知道自己最多能被拆分成多少个不同的自然数,使得这些自然数相乘的值等于被拆分的数。
输入描述:
第1行输入一个整数T,代表有T组数据。
第2-T+1行,每行输入一个整数n,代表需要被拆分的数。
数据保证:0<T≤100,0<n≤109。
输出描述:
输出一共T行,第i行输出一个整数,代表第i行输入的n最多可以被拆分成多少个不同的自然数。
示例1
输入
复制
3
1
4
12
输出
复制
1
2
3
说明
1可以被拆分为:1
4可以被拆分为:14(122是不允许的,因为有重复的数)
12可以被拆分为:126或134
示例2
输入
复制
1
114514
输出
复制
4
说明
114514可以被拆分为:12311847
很大的数的话最后一定剩下的只有那个大数的平方了
#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;
#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
//#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 out = 0)
{
char c;
while((c=getchar()) < 48 || c > 57);
while(c >= 48 && c <= 57) out=out*10+c-48,c=getchar();
return out;
}
const int N = 8e5 + 10;
const int M = 2e5 + 10;
const int mod = 77797;
const int PP = 13331;
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);
signed main(){
int T;
scanf("%lld", &T);
while(T --){
int n;
scanf("%lld", &n);
int cnt = 1;
for (int i = 2; i <= n && i <= 100000; i ++){
if (n % i == 0){
cnt ++;
n /= i;
}
}
// if (n > 100000) cnt ++;
cout << cnt << endl;
}
return 0;
}