2019 杭电多校 第三场

Posted wulitaotao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 杭电多校 第三场相关的知识,希望对你有一定的参考价值。

2019 Multi-University Training Contest 3

补题链接:2019 Multi-University Training Contest 3

1002 Blow up the city (HDU-6604)

题意

给定 \(n\) 个点和 \(m\) 条边的有向无环图,给出 \(q\) 次询问,每个询问给出 \(a\)\(b\),求有多少个点,满足该点删去后 \(a\)\(b\) 中至少一个点不能到达出度为 \(0\) 的点。

题解

支配树/灭绝树 拓扑排序 最近公共祖先

1006 Fansblog (HDU-6608)

题意

给定素数\(\ P(1e^9\leq P\leq 1e^14)\),试找出小于\(P\)的最大素数\(\ Q\),求出\(\ Q! \ mod \ P\)

题解

威尔逊定理 逆元 质数的密度分布 Miller-Rabin素数测试

威尔逊定理:当且仅当 \(P\) 为素数时:\((P - 1)!\equiv -1\ mod\ P\)

\((P-1)!\equiv(P-1)\ mod\ P\),由于 \((P - 1)! = (Q!) * (Q + 1) * (Q + 2) * ... * (P - 1)\),可得 \(Q!\ mod\ P=\frac (P - 1)(Q + 1) * (Q + 2) * ... * (P - 1)\ mod\ P=\frac 1(Q + 1) * (Q + 2) * ... * (P - 2)\ mod\ P\)

可以使用 \(Miller-Rabin\) 素数测试判断素数,也可直接使用试除法。
素数间的间隔不超过 \(600\) (素数间的大间隔(Large gaps between primes)),因此可直接从 \(P - 1\) 开始查找 \(Q\)
注意数很大,需要使用快速乘。(WA了好几发)

代码:

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

ll mulmod(ll a, ll b, ll m) 
    ll ans = 0;
    while (b) 
        if (b & 1) ans = (ans + a) % m;
        a = (a << 1) % m;
        b >>= 1;
    
    return ans % m;


ll qmod(ll a, ll b, ll m) 
    if(!b) return 1 % m;
    ll ans = 1;
    while (b) 
        if (b & 1) ans = mulmod(ans, a, m);
        a = mulmod(a, a, m);
        b >>= 1;
    
    return ans % m;


bool Miller_Rabbin(ll n, ll a) 
    ll d = n - 1, s = 0, i;
    while (!(d & 1)) 
        d >>= 1;
        s++;
    
    ll t = qmod(a, d, n);
    if (t == 1 || t == -1)
        return 1;
    for (i = 0; i < s; i++) 
        if (t == n - 1)
            return 1;
        t = mulmod(t, t, n);
    
    return 0;


bool is_prime(ll n) 
    ll i, tab[4] = 3, 4, 7, 11;
    for (i = 0; i < 4; i++) 
        if (n == tab[i])
            return 1;
        if (!n % tab[i])
            return 0;
        if (n > tab[i] && !Miller_Rabbin(n, tab[i]))
            return 0;
    
    return 1;


int main() 
    int T;
    scanf("%d", &T);
    while (T--) 
        ll n;
        scanf("%lld", &n);
        for (ll i = n - 1;; --i) 
            if (is_prime(i)) 
                ll ans = 1;
                for (ll j = i + 1; j <= n - 2; ++j) 
                    ans = mulmod(ans, qmod(j, n - 2, n), n);
                
                ans = (ans + n) % n;
                printf("%lld\n", ans);
                break;
            
        
    
    return 0;

1007 Find the answer (HDU-6609)

题意

给定 \(n\) 个整数 \(W_i(1\leq i\leq n)\) 和一个整数 \(m\),对于每个\(\ i(1\leq i \leq n)\),求至少需要删除多少个 \(W_k(1\leq k < i)\),使得\(\sum_j=1^iW_j\leq m\)。其中 \(1\leq W_i\leq m(1\leq i\leq n)\)

题解

multiset STL

神仙做法

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;

multiset<int> s;
ll a[maxn];

int main() 
    int T;
    scanf("%d", &T);
    while(T--) 
        int n; ll m;
        s.clear();
        scanf("%d %lld", &n, &m);
        for(int i = 1; i <= n; ++i) 
            scanf("%lld", &a[i]);
        
        ll sum = 0;
        int res = 0;
        for(int i = 1; i <= n; ++i) 
            int cnt = 0;
            ll tmp = sum;
            if(tmp + a[i] > m) 
                auto it = s.end();
                while(tmp + a[i] > m) 
                   --it;
                   tmp -= *it;
                   ++cnt;
                
            
            printf("%d ",cnt + res);
            s.insert(a[i]);
            sum += a[i];
            auto it = s.end();
            while(sum > m) 
                --it;
                sum -= *it;
                s.erase(s.find(*it));
                ++res;
            
        
        printf("\n");
    
    return 0;

以上是关于2019 杭电多校 第三场的主要内容,如果未能解决你的问题,请参考以下文章

2019杭电多校第三场 1004 Distribution of books

2020杭电多校第三场题解

2020杭电多校第三场

2019杭电多校第三场 1008 K-th Closest Distance

2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)

杭电多校第三场 A Ascending Rating