中国矿业大学(北京)第二届ACM程序设计公开赛(决赛)

素数回文
链接: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、 被一方大炮击中的另一方大炮会产生以攻击点为中心的3
3的波及区域,波及区域内如果有其他大炮则也会产生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可以被拆分为:1
26或134
示例2
输入
复制
1
114514
输出
复制
4
说明
114514可以被拆分为:1
2311847

很大的数的话最后一定剩下的只有那个大数的平方了

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值