2021ccpc网络赛重赛题解

B Kanade Doesn’t Want to Learn CG

比赛的时候是别人写的,想了一种其他的判法,就写了一下

直接判断点和抛物线的关系就行

这个题得注意一点 球可以碰到篮板的上沿

#include <bits/stdc++.h>
using namespace std;
#define ll long long

struct point{
    ll x, y;
};
struct line{
    ll a, b, c;
    int num(point P){
        ll u = (ll)P.x*P.x*a+P.x*b+c;
        if(u > P.y) return -1;
        else if(u == P.y) return 0;
        return 1;
    }
    void scan(){
        ll _a, _b, _c;
        scanf("%lld%lld%lld", &_a, &_b, &_c);
        a=_a,b=_b,c=_c;
    }
};

int main() {
    int t;
    line L;
    ll x0, x1, y0, y1, y2;
    point d1, d2, d3, h1, h2;
    scanf("%d", &t);
    while(t --) {
        L.scan();
        scanf("%lld%lld%lld%lld%lld", &x0, &x1, &y0, &y1, &y2);
        d1 = point{x0, y0};
        d2 = point{x1, y0};
        d3 = point{2ll*x1-x0, y0};
        h1 = point{x1, y1};
        h2 = point{x1, y2};
        if((L.num(d2) == 1) && (L.num(d1) == -1)) puts("Yes");
        else if((L.num(d1) == -1) && (L.num(d2) == -1) && (L.num(h2) != -1) && (L.num(d3) == 1)) puts("Yes");
        else puts("No");
    }
    return 0;
}

E Monopoly

比赛的时候就光想了,没推式子。最后正哥想出了思路。代码没敲完。

可以用 map套vector 也可以用 map套map

map套vector 需用判一些细节,比较麻烦,而 map套map 就不用

map 也能 lower_bound 也是写这个题的时候才知道的。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 100;
ll INF = 1e17;

ll n, m;
ll a[N], q[N], all;

int main() {
    int t; scanf("%d", &t);
    while(t --) {
        all = 0;
        map <ll, map<ll, ll>> mp;
        map <ll, ll> mp2;
        scanf("%lld%lld", &n, &m);
        for(ll i = 1;i <= n;i ++) {
            scanf("%lld", &a[i]);
            all = all + a[i];
        }

        if(all == 0) {
            for(ll i = 1;i <= n;i ++) {
                q[i] = q[i-1] + a[i];
                ll u = mp2[q[i]];
                if(u == 0) mp2[q[i]] = i;
            }
            ll x;
            while(m --) {
                scanf("%lld", &x);
                if(x == 0) puts("0");
                else if(mp2[x]) printf("%lld\n", mp2[x]);
                else printf("-1\n");
            }
            continue;
        }

        int st = 0;
        if(all < 0) {all = all * -1ll; st = 1;}

        for(ll i = 1;i <= n;i ++) {
            if(st) a[i] = -a[i];
            q[i] = q[i-1] + a[i];
            ll u = mp[(q[i] % all + all) % all][q[i]];
            if(u == 0) mp[(q[i] % all + all) % all][q[i]] = i;
        }

        for(auto &m : mp) m.second[-INF] = 1ll;

        ll x;
        while(m --) {
            scanf("%lld", &x);
            if(st) x = -x;
            if(x == 0) {puts("0");continue;}
            if(mp[(x%all + all) % all].size() < 2) {puts("-1"); continue;}
            auto it = mp[(x%all + all) % all].upper_bound(x);
            it --;
            if( it -> first != -INF ) printf("%lld\n", it->second + (x - it->first)/all*n);
            else printf("-1\n");
        }
    }
    return 0;
}

E Nun Heh Heh Aaaaaaaaaaa

dp题

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define ll long long
const int N = 1e5+100;
const ll mod = 998244353;

char s[20]={" nunhehheh"};
char ch[N];

ll dp[N][10];
ll sum[N][10];
ll a[N];

int main() {
    for(int i = 0;i < N;i ++)
        sum[i][0] = 1;
    int n;
    scanf("%d", &n);
    while(n --) {
        memset(dp, 0, sizeof dp);
        scanf("%s", ch+1);
        int l = strlen(ch+1);
        for(int i = 1;i <= l;i ++) {
            for(int j = 1;j <= 9;j ++) {
                if(ch[i] == s[j])
                    sum[i][j] = (sum[i-1][j-1] + sum[i-1][j]) % mod;
                else sum[i][j] = sum[i-1][j];

                if(ch[i] == s[j]) dp[i][j] = sum[i-1][j-1];
            }
        }

        a[l+1] = 1;
        for(int i = l;i >= 1;i --) {
            a[i] = a[i+1];
            if(ch[i] == 'a')
                a[i] = a[i] * 2 % mod;
        }

        ll ans = 0;
        for(int i = 1;i <= l;i ++) {
            if(a[i+1])
                ans = (ans + (dp[i][9] * (a[i+1]-1+mod) % mod)) % mod;
        }

        printf("%lld\n", ans);
    }
    return 0;
}

HSubpermutation

推公式的题

#include <bits/stdc++.h>
using namespace std;
#define ll long long

const ll mod = 1e9+7, N = 1e6+10;

ll n, x;
ll jie[N], fen[N];

ll qmi(ll a, ll k) {
	ll res = 1;
	while(k) {
		if(k & 1) res = res * a % mod;
		a = a * a % mod;
		k >>= 1;
	}
	return res;
}

void init() {
	jie[0] = 1;
	fen[0] = 0;
	for(int i = 1;i < N;i ++) {
		jie[i] = jie[i-1] * i % mod;
		fen[i] = qmi(jie[i], mod-2) + fen[i-1] % mod;
	}
}

int main() {
	int t;
	init();
	scanf("%d", &t);
	while(t --) {
		scanf("%lld%lld" ,&n, &x);
		ll ans = (jie[x] * ( (n-x+1)*jie[n-x] % mod + (x-1)*jie[n-x]%mod - fen[x-1] ) % mod + mod) % mod;
		printf("%lld\n", ans);
	}
    return 0;
}

J Bigraph Extension

这个题挺有意思的 比赛的时候根本分析不出来
多个问题同时解决会比较麻烦 先找一个切入点比较好一点 慢慢解决

看题解发现还挺巧的 构造题

第51行代码为什么是while呢 出个样例就知道了

输入为:

1
4 1
4 2

输出为:

7  
1 1
1 2
2 1
2 3
3 3
3 4
4 4
#include <bits/stdc++.h>
using namespace std;

const int N = 1010, M = 1010;

int n, m;
int a_d[N], b_d[N];
int h[N*2];

int find_h(int t) {
    if(h[t] == t) return t;
    return h[t] = find_h(h[t]); 
}

int hebing(int a, int b) {
    int fa = find_h(a);
    int fb = find_h(b);
    if(fa == fb) return 0;
    h[fa] = fb;
    return 1;
}

int main() {
    int t, l, r;
    scanf("%d", &t);
    while(t --) {
        scanf("%d%d", &n,&m);
        for(int i = 1;i <= n;i ++) {
            a_d[i] = b_d[i] = 0;
            h[i] = i; h[i + n] = i + n;
        }
        for(int i = 1;i <= m;i ++) {
            scanf("%d%d", &l, &r);
            hebing(l, r+n);
            a_d[l] ++; b_d[r] ++;
        }
        printf("%d\n", 2*n-m);

        int top = 1;
        for(int i = 1;i <= n;i ++) {
            for(int &j = a_d[i];j < 2;j ++) {
                int st = 0;
                for(int k = top;k <= n;k ++)
                    if(hebing(i, k + n)){
                        b_d[k] ++;
                        printf("%d %d\n", i, k);
                        st = 1;
                        break;
                    }
                if(st == 0) break;
                while (b_d[top] == 2) top ++;//为什么是while
            }
        }

        for(int i = 1;i <= n;i ++)
            if(a_d[i] == 1)
                printf("%d ", i);
        for(int i = 1;i <= n;i ++)
            if(b_d[i] == 1)
                printf("%d\n", i);
    }
    return 0;
}

K Jumping Monkey

#include <bits/stdc++.h>
using namespace std;

const int N = 100010, M = 2*N;

int n;
int h1[N], e1[M], ne1[M], idx1;
int h2[N], e2[M], ne2[M], idx2;
int head[N];
int num[N];
int depth[N];

struct node{
    int id, num;
    bool operator < (const node &no) const{
        return num < no.num;
    }
}z[N];

void add1(int a, int b) {
    e1[idx1] = b, ne1[idx1] = h1[a], h1[a] = idx1 ++;
}
void add2(int a, int b) {
    e2[idx2] = b, ne2[idx2] = h2[a], h2[a] = idx2 ++;
}
void init() {
    idx1 = idx2 = 0;
    memset(h1, -1, sizeof h1);
    memset(h2, -1, sizeof h2);
    for(int i = 1;i <= n;i ++) {
        head[i] = i;
        depth[i] = 0;
    }
}

int find_h(int t) {
    if(head[t] == t) return t;
    return head[t] = find_h(head[t]);   
}

void dfs(int u, int fa, int d){
    depth[u] = d;
    for(int i = h2[u];i != -1;i = ne2[i]) {
        int j = e2[i];
        if(j == fa) continue;
        dfs(j, u, d + 1);
    }
}

int main() {
    int t, l, r;
    scanf("%d", &t);
    while(t --) {
        scanf("%d", &n);
        init();
        for(int i = 0;i < n-1;i ++) {
            scanf("%d%d", &l, &r);
            add1(l, r); add1(r, l);
        }
        for(int i = 1;i <= n;i ++) { 
            scanf("%d", &l);
            num[i] = l;
            z[i].id = i;
            z[i].num = l;
        }
        sort(z+1, z+n+1);

        for(int i = 1;i <= n;i ++) {
            int u = z[i].id;
            for(int j = h1[u];j != -1;j=ne1[j]) {
                int k = e1[j];
                if(num[u] < num[k]) continue;
                int fa = find_h(k);
                add2(u, fa); add2(fa, u);
                head[fa] = u;
            }
        }

        dfs(z[n].id, 0, 1);

        for(int i = 1;i <= n;i ++) 
            printf("%d\n", depth[i]);
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值