首页 > 其他分享 >The 1st Universal Cup. Stage 7: Zaporizhzhia

The 1st Universal Cup. Stage 7: Zaporizhzhia

时间:2024-08-29 19:51:06浏览次数:13  
标签:std Cup int Zaporizhzhia Universal llsi ans include mod

Preface

在寝室白兰了一周多后也是终于等到徐神归来开始训练了

这场的题感觉比较偏数学了,感觉和之前打的一个 Tokyo 的 Open Cup 很像,因此后期挺坐牢的

4h 左右堪堪写出 7 题,最后全队 Rush D 结果发现暴力打表都打错了,怎么回事呢


A. Square Sum

这题在 去年暑假前集训数学专题 中做过类似的版本,只不过那个题的模数是没有平方质因子的奇质数

这题思路应该也是类似,但需要对 \(2\) 的情况进行一些讨论,代码先坑着有空来补


B. Super Meat Bros

题都没看,鉴定为不可做


C. Testing Subjects Usually Die

题都没看,鉴定为不可做


D. Triterminant

感觉思路没啥问题,就是三步走:解行列式——找合法序列的充要条件——计算最小操作次数

第一步就是线代课后习题的难度,不过推出式子后得到的结论很神秘,然后跑了个暴力打表发现并没有找到什么规律

后面看了 WIFI 的代码发现似乎是暴力写挂了(或者是前面搞错了),需要再反思下


E. Garbage Disposal

分类讨论题,首先特判掉 \(L=R\) 的情况

考虑若 \([L,R]\) 中有偶数个数,显然让相邻两个数两两配对一定合法

否则若 \([L,R]\) 中有奇数个数,若此时 \(L\) 为奇数,则可以让前 \(3\) 个数按:\((L,L+1),(L+1,L+2),(L+2,L)\) 的方式来配对

因为 \((L+2,L)\) 一定互质,而其余两组都是相邻的数因此也必然互质;剩下后面的偶数个数还是类似地两两配对即可

否则当 \(L\) 为偶数时一定无解,因为根据鸽笼原理,必然会有至少一对偶数要配对,显然无解

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int t,L,R;
int main()
{
    for (scanf("%d",&t);t;--t)
    {
        scanf("%d%d",&L,&R);
        if (L==R)
        {
            puts(L==1?"1":"-1"); continue;
        }
        if ((R-L+1)%2==0)
        {
            for (RI i=L;i+1<=R;i+=2)
            printf("%d %d ",i+1,i); putchar('\n');
        } else
        {
            if (L%2==0) { puts("-1"); continue; }
            printf("%d %d %d ",L+1,L+2,L);
            for (RI i=L+3;i+1<=R;i+=2)
            printf("%d %d ",i+1,i); putchar('\n');
        }
    }
    return 0;
}

F. Palindromic Polynomial

题都没看,鉴定为不可做


G. Palindromic Differences

徐神开场写的,我题目都没看

#include <bits/stdc++.h>

using llsi = long long signed int;
constexpr llsi mod = 1'000'000'009;

constexpr llsi $n = 500005;

constexpr llsi ksm(llsi a, llsi b) {
    llsi r = 1;
    while(b) {
        if(b & 1) r = r * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return r;
}

llsi fac[$n], facinv[$n], p2[$n];

void prep(int n) {
    fac[0] = 1; p2[0] = 1;
    for(int i = 1; i <= n; ++i) p2[i] = p2[i - 1] * 2 % mod;
    for(int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i % mod;
    facinv[n] = ksm(fac[n], mod - 2);
    for(int i = n; i >= 1; --i) facinv[i - 1] = facinv[i] * i % mod;
    return ;
}

int n, a[$n];

void work() {
    std::cin >> n;
    for(int i = 1; i <= n; ++i) std::cin >> a[i];
    std::sort(a + 1, a + n + 1);
    llsi ans = fac[n / 2];
    int cnt = 1;
    for(int i = 2, j = n - 1; ; ++i, --j) {
        if(a[i] + a[j] != a[i - 1] + a[j + 1]) {
            ans = 0;
            break;
        }
        if(i < j && a[i] == a[i - 1]) cnt++;
        else {
            ans = ans * facinv[cnt] % mod;
            if(a[i - 1] != a[j + 1]) ans = ans * p2[cnt] % mod;
            cnt = 1;
        }
        if(i >= j) break;
    }
    if((n & 1) && a[n / 2 + 1] * 2 != a[1] + a[n]) ans = 0;
    std::cout << ans << char(10);
    // if(n == 14) std::cout << fac[7] * p2[7] % mod << char(10);
    return ;
}

int main() {
    std::ios::sync_with_stdio(false);
    prep(500000);
    int T; std::cin >> T; while(T--) work();
    return 0;
}


H. Graph Isomorphism

神秘分类讨论题

注意到和一个图同构的图数量在没什么特殊限制时大概率是 \(n!\) 级别的,因此当 \(n\) 足够大时绝大多数图都是无解的

手玩一波会发现菊花图因为有一个 fixed point 的存在,因此恰好有 \(n\) 种同构图

与此同时比较隐蔽的还有菊花图的补图,即一个孤点加上一个完全图也是合法的

另外还有些特殊情况,例如点数小于等于 \(3\) 的图、完全图,最坑的是当 \(n=4\) 时四元环和每个点度数为 \(1\) 的图也是有解的

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int t,n,m,x,y,deg[N];
int main()
{
    for (scanf("%d",&t);t;--t)
    {
        scanf("%d%d",&n,&m);
        for (RI i=1;i<=n;++i) deg[i]=0;
        for (RI i=1;i<=m;++i)
        scanf("%d%d",&x,&y),++deg[x],++deg[y];
        if (n<=3) { puts("YES"); continue; }
        if (n==4&&m==2&&deg[1]==1&&deg[2]==1&&deg[3]==1&&deg[4]==1) { puts("YES"); continue; }
        if (n==4&&m==4&&deg[1]==2&&deg[2]==2&&deg[3]==2&&deg[4]==2) { puts("YES"); continue; }
        if (m==1LL*n*(n-1)/2) { puts("YES"); continue; }
        int center=0,outer=0;
        for (RI i=1;i<=n;++i)
        if (deg[i]==n-1) ++center; else if (deg[i]==1) ++outer;
        if (center==1&&outer==n-1) { puts("YES"); continue; }
        int iso=0,kernel=0;
        for (RI i=1;i<=n;++i)
        if (deg[i]==0) ++iso; else if (deg[i]==n-2) ++kernel;
        if (iso==1&&kernel==n-1) { puts("YES"); continue; }
        puts("NO");
    }
    return 0;
}

I. DAG Generation

不会 Counting 怎么办,我们只需要暴力打表并找规律即可轻松过题

首先计算相同的概率显然更简单,同时不妨把生成图的方式稍作变换,先随机固定一个排列,然后钦定边只能从前面的点连向后面的点,不难发现这种生产方式和原题的表述等价

考虑总的方案数作为分母是 \([n!\times 2^{\frac{n(n-1)}{2}}]^2\),现在我们要对每一种具体的方案去重后平方累计贡献得到分子

写一个暴力会发现分子形如 \(n!\times (2^1-1)\times (2^2-1)\times (2^n-1)\),因此最后答案的表达式即为:

\[1-\frac{(2^1-1)\times (2^2-1)\times (2^n-1)}{n!\times 2^{n(n-1)}} \]

#include <bits/stdc++.h>

using llsi = long long signed int;
constexpr llsi mod = 1'000'000'009;

constexpr llsi $n = 500005;

constexpr llsi ksm(llsi a, llsi b) {
    llsi r = 1;
    while(b) {
        if(b & 1) r = r * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return r;
}

llsi fac[$n], facinv[$n], p2[$n], hkr[$n];

void prep(int n) {
    fac[0] = 1; p2[0] = 1; hkr[0] = 1;
    for(int i = 1; i <= n; ++i) p2[i] = p2[i - 1] * 2 % mod;
    for(int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i % mod;
    facinv[n] = ksm(fac[n], mod - 2);
    for(int i = n; i >= 1; --i) facinv[i - 1] = facinv[i] * i % mod;
    return ;
}

int main() {
    std::ios::sync_with_stdio(false);
    prep(100000);
    hkr[1] = 1;
    for(int i = 2; i <= 100000; ++i) hkr[i] = hkr[i - 1] * (p2[i] - 1) % mod;
    int T; std::cin >> T; while(T--) {
        llsi n; std::cin >> n;
        llsi ans = hkr[n] * fac[n] % mod;
        ans = ans * ksm(fac[n] * ksm(2, n * (n - 1) / 2) % mod, (mod - 2) * 2) % mod;
        std::cout << (1 + mod - ans) % mod << char(10);
    }
}

J. Persian Casino

小清新 Counting 题,想清楚策略后就很简单了

注意到最优策略一定是先一直做,直到 rollback 的次数全部耗尽;接下来的部分怎么操作都不会改变答案的期望了

因此最坏情况下,若 \(2^m<n-m\),即前 \(m\) 轮就用完了 rollback,此时积攒的钱不够后面每轮投一块钱,此时无解

否则必然有解,考虑计算期望,不难发现最后的钱数只和倍增的轮次有关,不妨枚举最后恰好倍增了 \(k\) 次

分情况讨论,当 \(k<n\) 时,这种情形的概率为 \(C_{m-1}^{k-1}\times \frac{1}{2^k}\),钱数为 \(2^k\),因此总贡献为 \(\sum_{k=m}^{n-1} C_{m-1}^{k-1}=C_n^m\)

当 \(k=n\) 时,改为枚举一共用了多少次 rollback,总贡献为 \(\sum_{i=0}^{m-1} C_n^i\times \frac{1}{2^n}\times 2^n=\sum_{i=0}^{m-1} C_n^i\)

因此最后合并一下发现答案就是 \(\sum_{i=0}^{m} C_n^i\),计算十分容易

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005,mod=1e9+9;
int t,n,m,fact[N],ifac[N];
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline void init(CI n)
{
    fact[0]=1; for (RI i=1;i<=n;++i) fact[i]=1LL*fact[i-1]*i%mod;
    ifac[n]=quick_pow(fact[n]); for (RI i=n-1;i>=0;--i) ifac[i]=1LL*ifac[i+1]*(i+1)%mod;
}
inline int C(CI n,CI m)
{
    if (n<0||m<0||n<m) return 0;
    return 1LL*fact[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int main()
{
    for (scanf("%d",&t),init(1e5);t;--t)
    {
        scanf("%d%d",&n,&m);
        if (m<=20&&(1<<m)<n-m) { puts("bankrupt"); continue; }
        int ans=0; for (RI i=0;i<=m;++i) (ans+=C(n,i))%=mod;
        printf("%d\n",ans);
    }
    return 0;
}

K. Determinant, or...?

计算行列式的值的经典思路就是转为上/下三角矩阵后把对角线乘起来,因此考虑消元

不难发现原矩阵可以等分为四个部分,其中除左上角区域外的三个部分内的数完全相同

考虑把矩阵的上半部分减去下半部分,这样就可以把右上角部分全部变为 \(0\)

而左上角部分不难发现扔满足上述性质,递归处理即可将整个行列式变为下三角矩阵,总复杂度 \(O(n\log n)\)

#include <bits/stdc++.h>

constexpr int mod = 1'000'000'009;
int a[1 << 20];

int64_t calc(int l, int r) {
    if(r == l + 1) return a[l];
    int mid = (l + r) >> 1;
    for(int i = l; i < mid; ++i) a[i] = (a[i] + mod - a[i + r - mid]) % mod;
    return calc(l, mid) * calc(mid, r) % mod;
}

int main() {
    std::ios::sync_with_stdio(false);
    int n; std::cin >> n; n = 1 << n;
    for(int i = 0; i < n; ++i) std::cin >> a[i];
    std::cout << calc(0, n) << char(10);
    return 0;
}

L. Directed Vertex Cacti

题都没看,鉴定为不可做


M. Siteswap

祁神 solo 的一个神秘模拟题(?),我连题意都看不懂,好像细节挺多很容易写挂

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

const int N = 1e5+5;
int n, A[N];
bool vis[N];

void solve(){
    cin >> n;
    for (int i=0; i<n; ++i) cin >> A[i], vis[i]=false;
    int ans[3] = {0, 0, 0};

    for (int i=0; i<n; ++i) if (!vis[i]){
        if (0==A[i]){
            vis[i]=true; 
            continue;
        }

        if (A[i]%n==0){
            int res = A[i]/n;
            if (n%2==0) ans[i%2] += res;
            else{
                if (res%2==0){
                    ans[i%2] += (res+1)/2;
                    ans[(i+1)%2] += res/2;
                }else ans[2] += res;
            }
            continue;
        }

        int loops = 0;
        bool odd = false;
        int cur = i;
        while (!vis[cur]){
            int res = (cur+A[cur])/n;
            loops += res;
            if (A[cur]%2==1) odd=true;
            vis[cur]=true;
            cur = (cur+A[cur])%n;
        }

        if (!odd){
            // printf("n%2=%lld\n", n %2);
            if (n%2==0) ans[i%2] += loops;
            else{
                if (loops%2==0){
                    ans[i%2] += (loops+1)/2;
                    ans[(i+1)%2] += loops/2;
                }else ans[2] += loops;
            }
        }else ans[2] += loops;
    }

    cout << ans[0] << ' ' << ans[1] << ' ' << ans[2] << '\n';
}

signed main(){
    ios::sync_with_stdio(0); cin.tie(0);
    int t; cin >> t; while (t--) solve();
    return 0;
}

Postscript

感觉这场题都不太对我们队的好球区啊,这斯拉夫人怎么和日本人一样喜欢出一堆数学题呢

标签:std,Cup,int,Zaporizhzhia,Universal,llsi,ans,include,mod
From: https://www.cnblogs.com/cjjsb/p/18387457

相关文章

  • The 3rd Universal Cup. Stage 1: St. Petersburg Finalized Standings
    C.CherryPicking这道题用了一个类似ODT的题思路。首先我们可以想到是,如果删除某些选手,只有可能会导致区间的合并,不会导致区间的分裂。所以我们可以枚举一下$x$的值,然后找到需要删除的点。用set​维护相同且相邻区间,找到删除点所在的区间后,给区间长度减一。如果区间长度为空......
  • 题解:CF1032B Personalized Cup
    本题题意给一个字符串,将其分成等长度的字符串,但是分的行数不能超过\(5\)行,每行的长度不得超过\(20\)。如果无法等分的,则用*来补足长度。输出在行数最小的前提下,列数最少的一种方案。思路由于字符串范围最多也就\(20\times5\),直接分类讨论即可。ACcode#include<bits/st......
  • 【WCET 户厕】2nd Qingbai Cup
    T1考虑二分,然后怎么check。我们随便选一个点开始BFS地移动,如果以它为左上角的正方形可以覆盖整个局面中的所有空格子,那么整个边长就是可行的。容易证明随便选一个点开始是正确的。T2抽象题。看到数据范围容易有一个状压状物,然而\(2^n\)怎么都去不掉。根据某年NOI或W......
  • XXI Open Cup, Grand Prix of Tokyo
    Preface神秘沟槽Counting大赛,十个题全是模\(998244353\)有点逆天了开场发现G是去年暑假前集训的原,然后坐牢了大半天看榜发现包大爷切了B,然后跟了一手接下来慢慢把所有题都看了一遍,每个题都属于有点思路但不多中间和祁神把诈骗题I玩出来了,然后对着H硬套「PKUWC2018......
  • 串行通信协议--UART(Universal Asynchronous Receiver/Transmitter,通用异步收发传输器
    一、UART简介  UART广泛应用于微控制器和计算机之间的数据通信,如GPS模块、蓝牙模块、GSM模块等。UART是一种通用串行数据总线,用于异步通信,该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用于主机与辅助设备通信UART通常被集成于其他通讯接口的连结上。UA......
  • 【待做】【AI+安全】数据集:KDD CUP99
    https://mp.weixin.qq.com/s?__biz=Mzg5MTM5ODU2Mg==&mid=2247494059&idx=1&sn=fdbfa26d8a3fc53596e5c8fe061f22a6&chksm=cfcf5966f8b8d0709e0992983b7ea9ebfc4f0331758b732394515e75eda99f82cd4829128144&scene=21#wechat_redirect[当人工智能遇上安全]6.基于机器学习......
  • Python数据预处理+正态性检验+异常值处理+Q-Q图-K-S检验+相关性分析(2024MathorCup A题
    #数据预处理#正态性检验、Q-Q图、箱线图、直方图、相关性分析#Q-Q图importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltfromscipy.statsimportnormfromscipy.statsimportprobplota=pd.read_excel('附件1:小区基本信息.xlsx',engine='openpyxl'......
  • 【待做】【AI+安全】数据集:KDD CUP 99
    KDDCUP99KDDCUP99dataset是KDD竞赛在1999年举行时采用的数据集。1998年美国国防部高级规划署(DARPA)在MIT林肯实验室进行了一项入侵检测评估项目收集而来的数据,其竞争任务是建立一个网络入侵检测器,这是一种能够区分称为入侵或攻击的“不良”连接和“良好”的正常连接的预测模......
  • Pixelmator Pro 3.6.5 Archipelago (macOS Universal) - 专业图像编辑工具
    PixelmatorPro3.6.5Archipelago(macOSUniversal)-专业图像编辑工具Photoshop的卓越替代软件请访问原文链接:https://sysin.org/blog/pixelmator-pro-3/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgPixelmatorPro真正基于AppleMac技术构建,不像某些异类......
  • Picovoice Porcupine 自定义唤醒词不起作用,文件路径问题
    我在picovoice网站上训练了自定义唤醒词并下载了ZIP文件。然后我将其解压并复制文件路径。这是我的代码:importstructimportpyaudioimportpvporcupineporcupine=Nonepaud=Noneaudio_stream=Nonetry:porcupine=pvporcupine.create(access_key="blahblah",keyw......