直接判断两个数是否互质
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#pragma GCC optimize(2)
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define one first
#define two second
using namespace std;
typedef long long ll;
typedef pair<int, int > PII;
const int N = 1e6 + 5, mod = 1e9 + 9, INF = 0x3f3f3f3f;
int t, a, b;
int gcd(int a,int b){ return b==0?a:gcd(b,a%b); }
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
cin >> t;
while (t--) {
cin >> a >> b;
if (gcd(a, b) == 1) puts("Finite");
else puts("Infinite");
}
}
贪心
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#pragma GCC optimize(2)
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define one first
#define two second
using namespace std;
typedef long long ll;
typedef pair<int, int > PII;
const int N = 200, mod = 1e9 + 9, INF = 0x3f3f3f3f;
int t, a, b, c, flag, tmp, m, n;
char s1[N], s2[N];
int gcd(int a,int b){ return b==0?a:gcd(b,a%b); }
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// cin.tie(0);
// cout.tie(0);
// ios::sync_with_stdio(0);
cin >> t;
while (t--) {
tmp = 0;
mm(s2, 0);
cin >> n >> a >> b >> c;
scanf("%s", s1);
for (int i = 0; i < n; ++i) {
if (s1[i] == 'R') {
if (b > 0) {
tmp++;
b--;
s2[i] = 'P';
} else {
s2[i] = 'X';
}
} else if (s1[i] == 'P') {
if (c > 0) {
c--;
tmp++;
s2[i] = 'S';
} else {
s2[i] = 'X';
}
} else if (s1[i] == 'S') {
if (a > 0) {
tmp++;
a--;
s2[i] = 'R';
} else {
s2[i] = 'X';
}
}
}
if (n & 1) m = n / 2 + 1;
else m = n / 2;
// cout << tmp << " " << m << endl;
if (tmp < m) {
puts("NO");
continue;
} else {
for (int i = 0; i < n; ++i) {
if (s2[i] == 'X') {
if (a > 0) {
s2[i] = 'R';
a--;
} else if (b > 0) {
s2[i] = 'P';
b--;
} else if (c > 0) {
c--;
s2[i] = 'S';
}
}
}
printf("YES\n");
printf("%s\n", s2);
}
}
}
/*
7
2
1 1 0
RR
2
2 0 0
SS
2
2 0 0
RR
3
1 2 0
RRR
3
2 1 0
RRR
1
1 0 0
P
1
1 0 0
S
*/
如果字符中出现m或w就代表是由好的打印机发过来的,直接输出0。否则就dp推一下状态转移方程,后来发现如果当前字符为n或u并且前一个字符也为n或u就是dp[n] = dp[n - 1] + dp[n - 2],否则dp[n] = dp[n - 1]
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#pragma GCC optimize(2)
#define mm(i,v) memset(i,v,sizeof i);
#define mp(a, b) make_pair(a, b)
#define one first
#define two second
using namespace std;
typedef long long ll;
typedef pair<int, int > PII;
const int N = 1e5 + 5, mod = 1e9 + 7, INF = 0x3f3f3f3f;
char s[N];
int dp[N];
int ans, flag;
int pow_2(int x) {
int ans = 2;
for (int i = 1; i <= x; ++i)
ans *= 2;
return ans;
}
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// cin.tie(0);
// cout.tie(0);
// ios::sync_with_stdio(0);
scanf("%s", s);
flag = 0;
int len = strlen(s);
dp[0] = 1;
for (int i = 0; i < len; ++i) {
if (s[i] == 'm' || s[i] == 'w') {
flag = 1;
break;
}
if (i == 0) continue;
if (i == 1) {
if (s[i] == s[i - 1]) dp[i] = dp[i - 1] + 1;
else dp[i] = dp[i - 1];
continue;
}
if (s[i] == 'u' && s[i - 1] == 'u') dp[i] = (dp[i - 1] + dp[i - 2]) % mod;
else if (s[i] == 'n' && s[i - 1] == 'n') dp[i] = (dp[i - 1] + dp[i - 2]) % mod;
else dp[i] = dp[i - 1];
// if (s[i] == 'n') {
// if (i == 1) {
// if (s[i - 1] == 'n') dp[i] = dp[i - 1] * 2;
// else dp[i] = dp[i - 1];
// continue;
// }
// if (s[i - 1] == 'n' && s[i - 2] == 'n') dp[i] = dp[i - 1] + dp[i - 2];
// else if (s[i - 1] == 'n') dp[i] = (dp[i - 1] + 1) * dp[i - 1];
// else dp[i] = dp[i - 1];
// } else if (s[i] == 'u') {
// if (i == 1) {
// if (s[i - 1] == 'u') dp[i] = dp[i - 1] + 1;
// else dp[i] = dp[i - 1];
// continue;
// }
// if (s[i - 1] == 'n' && s[i - 2] == 'u') dp[i] = dp[i - 1] + dp[i - 2];
// else if (s[i - 1] == 'u') dp[i] = dp[i - 1] + 1;
// else dp[i] = dp[i - 1];
// } else {
// dp[i] = dp[i - 1];
// }
//
// cout << i << " " << dp[i] << endl;
}
if (flag == 1) {
puts("0");
} else {
cout << dp[len - 1] << endl;
}
}
题意:要使每个村庄都通上电,通电的方法是在这个村庄建发电站(花费ci)或者把这个村庄和一个有发电站的村庄连接起来(花费ki + kj的和乘上两个村庄的曼哈顿距离)
这题显然是最小生成树(感觉迪杰斯特拉也行)
解法:首先假设每个点都自建,那么每个点的代价就是自建代价。然后按照代价排序,用代价最小的点去更新后面那些点,如果能更新用电代价,就把那些点连接到当前点。然后进入下一轮循环,排除上一次代价最小的点,把剩下的点再次按照代价排序,然后用这些点中代价最小的去更新其他的,以此类推。
By MengWH, contest: Codeforces Round #597 (Div. 2), problem: (D) Shichikuji and Power Grid, Accepted, #
#include<bits/stdc++.h>
using namespace std ;
int n;
struct City {
int id;
long long x,y; //坐标
long long cc,kk; //自建的花费,连线的花费
bool self;//是否建站
int fa;//连线的站
bool operator < (const City & a)const {
return cc<a.cc;
}
} c[2005];
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
c[i].id=i;//发电站编号
c[i].self=1; //首先都默认是自建的
scanf("%lld%lld",&c[i].x,&c[i].y); //输入坐标
}
for(int i=1; i<=n; i++) scanf("%lld",&c[i].cc); //初始都为自建
for(int i=1; i<=n; i++) scanf("%lld",&c[i].kk);//连线
long long ans=0,selfnum=0;
for(int i=1; i<=n; i++) {
sort(c+i,c+1+n);//大概就是要随时排序,每次找到最小的,每次排序要排除前一次的,防止多加费用
ans+=c[i].cc; //费用
if(c[i].self) selfnum++; //判断是否自建
for(int j=i+1; j<=n; j++) {
long long cost=(c[i].kk+c[j].kk)*(abs(c[i].x-c[j].x)+abs(c[i].y-c[j].y));
if(cost<c[j].cc) {
c[j].cc=cost;
c[j].self=0;//放弃自建,说要已经和别的站建立了联系
c[j].fa=c[i].id;
}
}
}
printf("%lld\n%lld\n",ans,selfnum);
for(int i=1; i<=n; i++)
if(c[i].self) printf("%d ",c[i].id);
printf("\n%lld\n",n-selfnum);
for(int i=1; i<=n; i++)
if(!c[i].self) printf("%d %d\n",c[i].id,c[i].fa);
return 0;
}
E、F
......
本文精选了算法竞赛中的四个经典题目,包括互质数判断、贪心策略、动态规划及最小生成树问题,通过深入解析提供了高效解决方案。
308

被折叠的 条评论
为什么被折叠?



