2021年“图森未来杯”全国程序设计邀请赛(校外组)
C Countdown
print(189)
E Edge Game
题意:
给你一个无向树🌲,两个人在这个树上玩游戏,起点分别是a和b,每一次只能走临近的一个节点,问你谁会先踩到对方
思路:
直接判断连接二者的最短路径的奇偶性,奇数则输出Yes,否则是No
正常来说,求树上的最短路应该是用LAC叭,但是我这里使用的是dijkstra求的
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 500000 + 50
#define endl '\n'
#define mod 13331
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef long long ll ;
//不开longlong见祖宗!
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
//__________________dijkstra______________________
int n, m, s,t, tot;
int x, y, c;
int dist[MAX];
int head[MAX];
bool vis[MAX];
struct ran{
int to, next, val;
inline bool operator < (const ran &x)const{
return val > x.val;
}
};
ran tr[MAX], now, nextt;
priority_queue<ran>q;
void init(){
tot = 0;
mem(tr, 0);
mem(vis, 0);
mem(head, -1);
mem(dist, inf);
}
void built(int u, int v, int c){
tr[++tot].to = v;
tr[tot].val = c;
tr[tot].next = head[u];
head[u] = tot;
}
void dijkstra(){
dist[s] = 0;
now.to = s;
now.val = 0;
q.push(now);
while (!q.empty()) {
now = q.top();q.pop();
if(vis[now.to])continue;
vis[now.to] = true;
for(int i = head[now.to]; i != -1; i = tr[i].next){
int u = tr[i].to;
if(dist[u] > dist[now.to] + tr[i].val){
dist[u] = dist[now.to] + tr[i].val;
nextt.to = u;
nextt.val = dist[u];
q.push(nextt);
}
}
}
}
int main(){
io;
cin>>m;
init();
for(int i = 1; i <= m - 1; ++i){
cin>>x>>y;
built(x, y, 1);
built(y, x, 1);
}
cin>>s>>t;
dijkstra();
if(dist[t] % 2 == 1)cout<<"Yes\n";
else cout<<"No\n";
return 0;
}
G Group QQ Speed
题意:
N个人玩QQ飞车,每个人禁用一张地图,将这n个人分成m组,对于一个组内,如果有人禁用了a图,则比赛时不能使用a图,以此类推,问你最少需要多少张地图才能满足题意?
思路:
如果 m = 1,则需要 n + 1张
如果 n = m ,则需要 2 张
其他情况只需要 3 张
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 200000 + 50
#define endl '\n'
//#define mod 1000000007
//const int mod = 1e9 + 7;
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef long long ll ;
//不开longlong见祖宗!
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
int t, n, m;
int main(){
cin>>t;
while (t--) {
cin>>n>>m;
if(m == 1)cout<<n + 1<<endl;
else if(n == m)cout<<2<<endl;
else cout<<3<<endl;
}
return 0;
}
I I Love You
题意:
给两个字符串a,b,问能否通过删除操作,使得a变成b
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 10000 + 50
#define endl '\n'
//#define mod 1000000007
//const int mod = 1e9 + 7;
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef long long ll ;
//不开longlong见祖宗!
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
string s, ss, sss;
int main(){
cin>>s>>ss;
for(int i = 0; i < ss.size(); ++i){
ll a = s.find(ss[i]);
if(a != -1){
s.erase(0, a);
}
else {
cout<<"No\n";
return 0;
}
}
cout<<"Yes\n";
return 0;
}
K K-Primes
题意:
给你一个 l 一个 k,问你[l, l + 2 * k) 中是否至少有k + 1个质数
思路1:
l 到 l + 2 * k – 1,一共有2 * k个数,而除了2以外都每一个偶数都不是素数,所以,如果 l != 2时,这2 * k个数中最多只要k个素数,是No,
而当 l = 2时,只有{2,3}{2,3,4,5}{2,3,4,5,6,7}这三组是Yes,其他都是No
思路2:
直接计算这个区间内有多少个质数
这里就可以拿出之前在网上不知道哪里嫖来的板子,用的是DP来求小于等于n的素数的个数,数组开的是
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 10000 + 50
#define endl '\n'
//#define mod 1000000007
//const int mod = 1e9 + 7;
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
//typedef long long ll ;
//不开longlong见祖宗!
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
typedef long long LL;
const int N = 2e7+7;
LL L[N],R[N];
LL primepi(LL n){
LL rn = (LL)sqrt(n+0.2);
for(LL i=1;i<=rn;++i) R[i]=n/i-1;
LL ln = n/(rn+1)+1;
for(LL i=1;i<=ln;++i) L[i]=i-1;
for(LL p=2;p<=rn;++p){
if(L[p]==L[p-1]) continue;
for(LL i=1,tn=min(n/(p*p),rn);i<=tn;++i){
R[i] -= (i*p<=rn?R[i*p]:L[n/(i*p)])-L[p-1];
}
for(LL i=ln;i>=p*p;--i){
L[i] -= L[i/p]-L[p-1];
}
}
return R[1];
}
int n, m, k;
int main(){
n = IntRead();
k = IntRead();
m = n + k * 2 - 1;
LL ans = primepi(m) - primepi(n - 1);
if(ans > k)cout<<"Yes\n";
else cout<<"No\n";
return 0;
}