[2020牛客多校第一场]Coda的题解集

被暴打了。

会先写比赛中过题数100+的题目,其他的以后再补。

施工中,未完待续…


F Infinite String Comparision

一开始想到的是对比到lcm(|a|,|b|),意料之中T了。

后来脑补了一种方法,把较长的字符串x2,然后把较短的字符串xN,直到超过翻倍后的长字符串,以展现出循环中两个字符串所有的特性,拿到了AC。

至于正确的解法,要使用到 The Periodicity Lemma,详见叉姐知乎:

A note on the proof of the Periodicity Lemma

事实上只需要微调一下T掉的代码,把lcm(|a|,|b|)改成|a|+|b|+gcd(|a|,|b|),就是正解了。

#include
using namespace std;
string a,b;
int la,lb;
int gcd(int a,int b)
{
    return b ? gcd(b,a%b) : a;
}
int main()
{
    while(cin>>a>>b)
    {
        la=a.length(),lb=b.length();
        int cnt=0,maxcnt=la+lb+gcd(la,lb);
        for(int i=0,j=0;;i++,j++)
        {
            if(a[i]<b[j])
            {cout<<"<"<<endl;break;}
            if(a[i]>b[j])
            {cout<<">"<<endl;break;}
            if(i+1==la) i=-1;
            if(j+1==lb) j=-1;
            cnt++;
            if(cnt==maxcnt)
            {cout<<"="<<endl;break;}
        }
    }
}

J Easy Integration

看到数论直接懵。

正解中提到了Wallis’ integrals和伽马函数之类,没有看懂,浏览其他博客时还看到了贝塔函数和分部积分之类的方法,先挖个坑,以后再填(大概)。

个人的想法还是通过找规律获得(n!)^2/(2n+1)!的通式,计算通式时会用到快速幂,逆元,费马小定理,具体原理在《挑战》P122和P291有解释。

#include
#define int long long
using namespace std;
const int N=2e6+7;
const int mod=998244353;
int fac[N];
int mod_pow(int x,int n)
{
    int res=1;
    while(n>0)
    {
        if(n&1)
            res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
signed main()
{
    int n;
    fac[1]=1;
    for(int i=2;i<N;i++)
        fac[i]=fac[i-1]*i%mod;
    while(cin>>n)
        cout<<fac[n]*fac[n]%mod*mod_pow(fac[2*n+1],mod-2)%mod<<endl;
}

I 1 or 2

套 模 板!!!

如果d=1,就是标准的一般图完美匹配,求个最大匹配判断一下就行,但是这题遇到d=2的情况需要分点。一般图最大匹配两种解法,一种是最常见到的带花树,还有一种是Tutte矩阵,《挑战》上带花树提都没提,就花了半页告诉你用Tutte矩阵算,于是因为没学过线代而看不懂的我直接跳过了。。。

考场上无论是出于模板长度还是运行效率,理所当然的会选择Tutte矩阵,不过作为学习,还是顺带套个带花树的代码。

叉姐Tutte矩阵模板:

#include 

const int N = 50;
const int M = 100;
const int MOD = 1e9 + 7;

int inverse(int a)
{
    return a == 1 ? 1
           : static_cast<uint64_t>(MOD - MOD / a) * inverse(MOD % a) % MOD;
}

template<int V>
int tutte(int n, const std::vector<std::pair<int, int>> &edges, int seed)
{
    static int mat[V][V];
    memset(mat, 0, sizeof(mat));
    std::mt19937 gen(seed);
    std::uniform_int_distribution<int> dist(1, MOD - 1);
    for (auto &&e : edges)
    {
        auto x = dist(gen);
        mat[e.first][e.second] = x;
        mat[e.second][e.first] = MOD - x;
    }
    int rank = 0;
    for (int j = 0; j < n; ++j)
    {
        int pivot = rank;
        while (pivot < n && !mat[pivot][j])
        {
            pivot++;
        }
        if (pivot < n)
        {
            for (int k = 0; k < n; ++k)
            {
                std::swap(mat[rank][k], mat[pivot][k]);
            }
            const uint64_t inv = inverse(mat[rank][j]);
            for (int i = rank + 1; i < n; ++i)
            {
                if (mat[i][j])
                {
                    const uint64_t tmp = inv * mat[i][j] % MOD;
                    for (int k = j; k < n; ++k)
                    {
                        mat[i][k] += MOD - tmp * mat[rank][k] % MOD;
                        if (mat[i][k] >= MOD)
                        {
                            mat[i][k] -= MOD;
                        }
                    }
                }
            }
            rank++;
        }
    }
    return rank;
}

#ifndef NO_MAIN

int deg[N];

int main()
{
    int n, m;
    while (scanf("%d%d", &n, &m) == 2)
    {
        int demand = 0;
        for (int i = 0; i < n; ++i)
        {
            scanf("%d", deg + i);
            demand += deg[i];
        }
        std::vector<std::pair<int, int>> edges;
        for (int i = 0, a, b; i < m; ++i)
        {
            scanf("%d%d", &a, &b);
            a--, b--;
            if (deg[a] == 2)
            {
                std::swap(a, b);
            }
            if (deg[a] == 2)
            {
                edges.emplace_back(a << 1 | 0, n + i << 1 | 0);
                edges.emplace_back(a << 1 | 1, n + i << 1 | 0);
                edges.emplace_back(b << 1 | 0, n + i << 1 | 1);
                edges.emplace_back(b << 1 | 1, n + i << 1 | 1);
                edges.emplace_back(n + i << 1 | 0, n + i << 1 | 1);
                demand += 2;
            }
            else if (deg[b] == 2)
            {
                edges.emplace_back(a << 1, b << 1 | 0);
                edges.emplace_back(a << 1, b << 1 | 1);
            }
            else
            {
                edges.emplace_back(a << 1, b << 1);
            }
        }
        puts(tutte<(N + M) << 1>(n + m << 1, edges, 0) == demand ? "Yes" : "No");
    }
}
#endif

带花树:

正在写...

你可能感兴趣的:([2020牛客多校第一场]Coda的题解集)