2019 沈阳网络赛 8/11

吐槽一下出题人英语还是要好好学一下,然后就是别题意全从问答拿,还有数据不知道什么鬼

A

B

bfs就行,题意问答拿

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iomanip>

using namespace std;

int const N = 200005;

bool isans[N], ismon[N], is1[N], col[N];
double ans[N];
int num[N];
int n, m, K;

struct edge {
    int y, next;
} e[N << 1];
int last[N], ne;

void addedge(int x, int y) {
    e[++ne].y = y;
    e[ne].next = last[x]; 
    last[x] = ne;
}

int g[N], cnt;
void bfs(int x) {
    cnt = 0;
    queue<int> q;
    q.push(x);
    col[x] = 1;
    while (q.empty() == 0) {
        int now = q.front();
        q.pop();
        g[++cnt] = now;
        for (int i = last[now]; i; i = e[i].next) 
            if (col[e[i].y] == 0 && ismon[e[i].y] == 0) {
                q.push(e[i].y);
                col[e[i].y] = 1;
            }
    }
    for (int i = 1; i <= cnt; ++i)
        num[g[i]] = cnt;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d%d", &n, &m, &K);
        for (int i = 1; i <= n; ++i) {
            last[i] = 0;
            ismon[i] = 0;
            col[i] = 0;
            isans[i] = 0;
            is1[i] = 0;
            ans[i] = 0;
            num[i] = 0;
        }
        ne = 0;
        for (int i = 1; i <= m; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            addedge(x, y);
            addedge(y, x);
        }
        for (int i = 1; i <= K; ++i) {
            int x;
            scanf("%d",&x);
            ismon[x] = 1;
        }
        bfs(1);
        for (int i = 1; i <= cnt; ++i) {
            is1[g[i]] = 1;
            for (int j = last[g[i]]; j != 0; j = e[j].next) 
                if (ismon[e[j].y])
                    isans[e[j].y] = 1;
        }
        int ans1 = cnt;
        for (int i = 1; i <= n; ++i)
            if (col[i] == 0 && ismon[i] == 0) 
                bfs(i);
        for (int i = 1; i <= n; ++i)
            if (isans[i]) {
                int du = 0;
                for (int j = last[i]; j; j = e[j].next) 
                    //if (ismon[e[j].y] == 0) 
                    	++du;
                for (int j = last[i]; j; j = e[j].next) 
                    //if (ismon[e[j].y] == 0) 
                    {
                        int s = ans1;
                        if (is1[e[j].y] == 0) 
                            s += num[e[j].y];
                        ans[i] += 1.0 * s / du;
                    }
            }
        double anss = 0;
        for (int i = 1; i <= n; ++i)
            anss = max(anss, ans[i]);
        cout << fixed << setprecision(10) << anss << '\n';
    }
}

C

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

using ll = long long;

int const N = 10005;

ll f[N];
int n, m;

int main() {
    while (scanf("%d%d", &n, &m) != EOF) {
        for (int i = 1; i <= 1e4; ++i)
            f[i] = 1e18;
        f[0] = 0;
        for (int i = 1; i <= n; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            for (int j = y; j <= 1e4; ++j)
                f[j] = min(f[j], f[j - y] + x);
        }
        ll ans = 1e18, ans2 = -1;
        for (int i = m; i <= 1e4; ++i)
            if (f[i] <= ans) {
                ans = f[i];
                ans2 = i;
            }
        cout << ans << ' ' << ans2 << '\n';
    }
}

D

树D合并一下就行。

#include <array>
#include <iostream>
#include <algorithm>
#include <cstdint>

using i64 = int64_t;
const i64 MOD = 1000000007;

struct Graph {
    struct E {
    	int to, w;
    };
    
    using Arr = std::array<int, 3>;
    
    int n;
    std::vector<std::vector<E>> es;
    std::vector<Arr> cnt;
    std::vector<Arr> sum;
    Arr ans;
    
    Graph(int n): n(n), es(n), cnt(n), sum(n), ans() {}
    
    void adde(int a, int b, int w) {
        es[a].push_back({ b, w });
    }
    
    void dfs(int c, int fa) {
        cnt[c][0] = (cnt[c][0] + 1) % MOD;
        // sum[c][0] += 0;
        
        for (auto &nxt: es[c])
        	if (nxt.to != fa) {
                dfs(nxt.to, c);
                
                Arr ccnt = {}, csum = {};
                for (int i = 0; i < 3; ++i) {
                    int idx = (i + nxt.w) % 3;
                    ccnt[idx] = cnt[nxt.to][i];
                    csum[idx] = ((i64)cnt[nxt.to][i] * nxt.w + sum[nxt.to][i]) % MOD;
                }
                //std::cerr << "cur " << ccnt[0] << ' ' << ccnt[1] << ' ' << ccnt[2] << '\n';
                //std::cerr << "sum " << csum[0] << ' ' << csum[1] << ' ' << csum[2] << '\n';
                for (int i = 0; i < 3; ++i)
                    for (int j = 0; j < 3; ++j) {
                        int tg = (i + j) % 3;
                        ans[tg] = (ans[tg] + (i64)sum[c][i] * ccnt[j] + (i64)cnt[c][i] * csum[j]) % MOD;
                    }
                //std::cerr << "ans " << ans[0] << ' ' << ans[1] << ' ' << ans[2] << '\n';
                
                for (int i = 0; i < 3; ++i) {
                    cnt[c][i] = (cnt[c][i] + ccnt[i]) % MOD;
                    sum[c][i] = (sum[c][i] + csum[i]) % MOD;
                    
                    //std::cerr << "mgcur " << cnt[c][0] << ' ' << cnt[c][1] << ' ' << cnt[c][2] << '\n';
                    //std::cerr << "mgsum " << sum[c][0] << ' ' << sum[c][1] << ' ' << sum[c][2] << '\n';
                }
            }
    }
};

int main () {
    std::ios::sync_with_stdio(false);
    
    int n;
    while (std::cin >> n) {
        Graph g { n };
        for (int i = 0; i < n - 1; ++i) {
            int a, b, w;
            std::cin >> a >> b >> w;
            g.adde(a, b, w);
            g.adde(b, a, w);
        }
        
        g.dfs(0, 0);
        auto ans = g.ans;
        for (int i = 0; i < 3; ++i) {
            ans[i] = ans[i] * 2 % MOD;
            std::cout << ans[i];
            if (i != 2)
            	std::cout << ' ';
        }
        std::cout << '\n';
    }
    
    return 0;
}

E

F

这个F真的把我们搞飞了,以为二分套二分不能过,我们就直接二分上界,但是不是所有大于这个上界的数直接挪到下界之下就行,要尽可能的把多一点的数小于上界,让下界更大才行。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <utility>
#include <cstdlib>
#include <cstring>
#include <cassert>

using namespace std;

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

int const N = 500005;

int a[N], n, m;
int aver;

pll chk(ll lim) {
    ll sum = 0;
    for (int i = 1; i <= n; ++i)
        if (a[i] >= lim)
            sum += a[i] - lim;
    if (sum < m)
		for (int i = 1; i < n; ++i)
			if (a[i] >= lim && sum < m)
				++sum;
    ll inf = 1e18;
    ll s = 0;
    for (int i = 1; i <= n; ++i) {
        s += a[i];
        if (1ll * a[i] * i - s > sum) {
            ll t = 1ll * a[i] * i - s;
            t = a[i] - (t - sum + i - 2) / (i - 1);
            return { lim - t, sum };
        }
    }
    ll t = 1ll * n * a[n] - s;
    return { lim - (a[n] + (sum - t) / n), sum };
}

int main() {
    //ios::sync_with_stdio(0);
    while (scanf("%d%d", &n, &m) != EOF) {
        for (int i = 1; i <= n; ++i)
        	scanf("%d", &a[i]);
        sort(a + 1, a + n + 1);
        ll l = *min_element(a + 1, a + n + 1);
        ll r = *max_element(a + 1, a + n + 1);
        ll ans = 1e18;
        ll sum = 0;
        for (int i = 1; i <= n; ++i)
            sum += a[i];
        ll flag = sum % n ? 1 : 0, ttt = 1e18;
        /*
        for (int i = l; i <= r; ++i) {
        	cerr << i << ' ' << chk(i).first << ' ' << chk(i).second << '\n';
        	if (chk(i).second <= m)
        		ttt = min(ttt, chk(i).first);
        }
        ttt = max(ttt, flag);
        */
        while (l <= r) {
            ll mid = (l + r) >> 1;
            auto t = chk(mid);
            t.first = max(t.first, flag);
            //cerr << l << ' ' << r << ' ' << mid << ' ' << t.first << ' ' << t.second << ' '<< m << '\n';
            if (t.second <= m) {
                ans = min(ans, t.first);
                r = mid - 1;
            } else
            	l = mid + 1;
        }
        //cerr << ttt << ' ' << ans << '\n';
        //assert(ans == ttt);
        cout << ans << '\n';
    }
}

G

这种题真的没什么意思,泰勒展开算一下,后面的项就小于精度了。

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

const int maxn = 1000010;
const int CNT = 32;
char s[maxn];
double tbl[CNT];

int main() {
    double x = 5.0 / 3.0;
    for (int i = 1; i < CNT; ++i) {
    	tbl[i] = x;
        x = (3.0 + 5.0 * x) / (2.0 + 3.0 * x);
        //std::cerr << std::fixed << std::setprecision(16) << x << '\n';
    }
    
    int T;
    cin >> T;
    while(T--) {
        double a;
        cin >> s >> a;
        int n = strlen(s);
        int nn = 0;
        for (int i = 0; i < n; ++i) {
        	nn = nn * 10 + (s[i] - '0');
        	if (nn >= CNT) {
        		nn = CNT - 1;
        		break;
			}
		}
		
        double ans = tbl[nn] * a;
        std::cout << std::fixed << std::setprecision(10) << ans << '\n';
    }
}

H

模拟就行。

#include <iostream>
#include <string>
#include <string.h>
#include <assert.h>
#include <algorithm>
using namespace std;

const int maxn = 100010;

struct Person {
    string name;
    int card[20];
    int rk[10];
    bool operator < (const Person& b) const {
        for(int i = 0;i < 5;i++) {
            if(rk[i] != b.rk[i]) return rk[i] > b.rk[i];
        }
        return name < b.name;
    }
    void read() {
        memset(rk,0,sizeof(rk));
        cin >> name;
        char s[20];
        cin >> s;
        int n = strlen(s);
        int cnt = 0;
        for(int i = 0;i < n;i++) {
            if(s[i] == '1') {
                card[cnt++] = 10;
                i++;
            }
            else if(s[i] == 'A') {
                card[cnt++] = 1;
            }
            else if(s[i] == 'J') {
                card[cnt++] = 11;
            }
            else if(s[i] == 'Q') {
                card[cnt++] = 12;
            }
            else if(s[i] == 'K') {
                card[cnt++] = 13;
            }
            else {
                card[cnt++] = s[i]-'0';
            }
        }
        sort(card,card+5);
    }
}ps[maxn];

int RStr(Person& p,const int* c) {
    if(c[0] == 1 && c[1] == 10 && c[2] == 11 && c[3] == 12 && c[4] == 13) {
        p.rk[0] = 10;
        return 1;
    }
    return 0;
}

int straight(Person& p,const int* c) {
    for(int i = 1;i < 5;i++) if(c[i] != c[i-1]+1) {
    	return 0;
    }
    p.rk[0] = 9;
    p.rk[1] = c[4];
    return 1;
}

int four(Person& p,const int* c) {
    int flg = c[0];
    for(int i = 1;i < 4;i++) if(c[i] != c[i-1]) flg = 0;
    if(flg) {
    	p.rk[0] = 8;
        p.rk[1] = flg;
        p.rk[2] = c[4];
        return 1;
    }
    flg = c[4];
    for(int i = 2;i < 5;i++) if(c[i] != c[i-1]) flg = 0;
    if(flg) {
    	p.rk[0] = 8;
        p.rk[1] = flg;
        p.rk[2] = c[0];
        return 1;
    }
    return 0;
}

int full(Person& p,const int* c) {
    int flg = c[0];
    for(int i = 1;i < 3;i++) if(c[i] != c[i-1]) flg = 0;
    if(flg && c[3] == c[4]) {
        p.rk[0] = 7;
        p.rk[1] = flg;
        p.rk[2] = c[3];
        return 1;
    }
    flg = c[4];
    for(int i = 3;i < 5;i++) if(c[i] != c[i-1]) flg = 0;
    if(flg && c[0] == c[1]) {
        p.rk[0] = 7;
        p.rk[1] = flg;
        p.rk[2] = c[0];
        return 1;
    }
    return 0;
}

int three(Person& p,const int* c) {
    int flg = c[0];
    for(int i = 1;i < 3;i++) if(c[i] != c[i-1]) flg = 0;
    if(flg) {
        p.rk[0] = 6;
        p.rk[1] = flg;
        p.rk[2] = c[3]+c[4];
        return 1;
    }
    flg = c[1];
    for(int i = 2;i < 4;i++) if(c[i] != c[i-1]) flg = 0;
    if(flg) {
        p.rk[0] = 6;
        p.rk[1] = flg;
        p.rk[2] = c[0]+c[4];
        return 1;
    }
    flg = c[4];
    for(int i = 3;i < 5;i++) if(c[i] != c[i-1]) flg = 0;
    if(flg) {
        p.rk[0] = 6;
        p.rk[1] = flg;
        p.rk[2] = c[0]+c[1];
        return 1;
    }
    return 0;
}

int twoPair(Person& p,const int* c) {
    int p1 = 0,p2 = 0;
    for(int i = 1;i < 5;i++) {
        if(c[i] == c[i-1]) {
            if(p1) p2 = c[i];
            else p1 = c[i];
        }
    }
    if(p1 && p2) {
        p.rk[0] = 5;
        p.rk[1] = max(p1,p2);
        p.rk[2] = min(p1,p2);
        if(c[0] != c[1]) p.rk[3] = c[0];
        else if(c[4] != c[3]) p.rk[3] = c[4];
        else p.rk[3] = c[2];
        return 1;
    }
    return 0;
}

int Pair(Person& p,const int* c) {
    for(int i = 1;i < 5;i++) {
        if(c[i] == c[i-1]) {
        	p.rk[0] = 4;
            p.rk[1] = c[i];
            for(int j = 0;j < 5;j++) {
                if(j != i && j != i-1) p.rk[2] += c[j];
            }
            return 1;
        }
    }
    return 0;
}

void getRk(Person& p) {
    if(RStr(p,p.card)) return ;
    else if(straight(p,p.card)) return;
    else if(four(p,p.card)) return;
    else if(full(p,p.card)) return;
    else if(three(p,p.card)) return;
    else if(twoPair(p,p.card)) return;
    else if(Pair(p,p.card)) return;
    else {
        p.rk[0] = 3;
        for(int i = 0;i < 5;i++) {
			p.rk[1] += p.card[i];
			cerr << p.card[i] << endl;
		}
    }
}

int main() {
    int n;
    while(cin >> n) {
        for(int i = 0;i < n;i++) {
            ps[i].read();
            getRk(ps[i]);
        }
        sort(ps,ps+n);
        for(int i = 0;i < n;i++) {
            cout << ps[i].name << endl;
        }
    }
    return 0;
}

I

J

gg我用之前的比赛账号交的题,然后账号注销了,没有拿到代码。
不过很简单公不公布代码都行。答案就是
1 X + 1 + 1 X + 2 + . . . + 1 n \frac{1}{X+1}+\frac{1}{X+2}+...+\frac{1}{n} X+11+X+21+...+n1
然后再用 1 1 1减去就行
不过要注意到 X ≥ n 2 X \geq \frac{n}{2} X2n
于是就反面考虑。
分母显然是 n ! n! n!
分子显然就是
n ! − ∑ i = X + 1 n C ( n , i ) ( i − 1 ) ! ( n − i ) ! n! - \sum_{i = X+1}^n C(n, i) (i - 1)! (n - i)! n!i=X+1nC(n,i)(i1)!(ni)!
化简就得到答案了。只要知道轮换的个数是 ( n − 1 ) ! (n-1)! (n1)!,置换的个数是 n ! n! n!就能做

K

理解的题意和出题人想表达的不同,但是比赛时一发过了,不想理会了。出题人英语什么鬼啊?数据又是很么鬼啊?
出于上诉原因不放代码出来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值