2021年“图森未来杯”全国程序设计邀请赛(校外组)

2021年“图森未来杯”全国程序设计邀请赛(校外组)

C Countdown

print(189)

E Edge Game

题意:

给你一个无向树,两个人在这个树上玩游戏,起点分别是a和b,每一次只能走临近的一个节点,问你谁会先踩到对方

思路:

直接判断连接二者的最短路径的奇偶性,奇数则输出Yes,否则是No

正常来说,求树上的最短路应该是用LAC叭,但是我这里使用的是dijkstra求的

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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的素数的个数,数组开的是 n \sqrt{n} n 的,时间复杂度是 O ( n l o g n ) O(\frac{n}{logn}) O(lognn),十分牛逼

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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;
}

你可能感兴趣的:(图森未来杯,ACM)