2025多校冲刺省选模拟赛14

2025多校冲刺省选模拟赛14

T1 A. 游戏 0pts

  • 原题: QOJ 9300. So Many Possibilities...

  • 初中信息奥赛模拟测试 T4 ZEW 玩 thd ,考虑将攻击次数攒起来,仅通过其对应的随从死亡状态推出贡献。

  • 考虑状压,设 fi,S 表示一共攻击了 i 次,随从死亡状态为 S 时用来攻击随从的操作的贡献。死亡人数不变时直接继承 ×1|S| 即可,死亡人数加一时在前面任选 ax1 步乘以组合数即可。

  • 然后考虑 U \ S 时的方案数统计,背包预处理的时间复杂度为 O(2nm2) ,但跑不过因子集和很难卡满所以每次重新计算的 O(2nnm2) ,可以使用 NTT/FFT 优化至 O(2nmlogm)

    点击查看预处理代码
    const int p=998244353;
    int a[210],inv[210],jc_inv[210],C[210][210],sum[(1<<15)+10],f[2][(1<<15)+10],g[210][(1<<15)+10];
    int lowbit(int x)
    {
        return (x&(-x));
    }
    int main()
    {
    #define Isaac
    #ifdef Isaac
        freopen("game.in","r",stdin);
        freopen("game.out","w",stdout);
    #endif
        int n,m,ans=0,s,i,j;
        cin>>n>>m;
        for(i=1;i<=n;i++)  cin>>a[i];
        inv[1]=C[0][0]=C[1][0]=C[1][1]=1;
        for(i=2;i<=m;i++)
        {
            inv[i]=1ll*(p-p/i)*inv[p%i]%p;
            C[i][0]=1;
            for(j=1;j<=i;j++)  C[i][j]=(C[i-1][j-1]+C[i-1][j])%p;
        }
        for(s=0;s<(1<<n);s++)
        {
            for(i=0;i<n;i++)
            {
                if((s>>i)&1)  sum[s]+=a[i+1];
            }
        }
        f[0][0]=1;
        for(i=0;i<m;i++)
        {
            memset(f[(i+1)&1],0,sizeof(f[(i+1)&1]));
            for(s=0;s<(1<<n);s++)
            {
                if(i-sum[s]<0)  continue;
                f[(i+1)&1][s]=(f[(i+1)&1][s]+1ll*f[i&1][s]*inv[n-__builtin_popcount(s)]%p)%p;
                for(j=0;j<n;j++)
                {
                    if(((s>>j)&1)==0&&i-sum[s]>=a[j+1]-1)
                        f[(i+1)&1][s|(1<<j)]=(f[(i+1)&1][s|(1<<j)]+
                        1ll*f[i&1][s]*inv[n-__builtin_popcount(s)]%p*C[i-sum[s]][a[j+1]-1]%p)%p;
                }
            }
        }
        for(s=0;s<(1<<n);s++)  g[0][s]=1;
        for(s=1;s<(1<<n);s++)
        {
            for(i=1;i<=m;i++)
            {
                for(j=0;j<=min(i,a[__builtin_ctz(s)+1]-1);j++)
                    g[i][s]=(g[i][s]+1ll*g[i-j][s^lowbit(s)]*C[i][j]%p)%p;
            }
        }
        for(s=0;s<(1<<n);s++)
        {
            if(m-sum[s]>=0)
                ans=(ans+1ll*f[m&1][s]*g[m-sum[s]][((1<<n)-1)^s]%p*__builtin_popcount(s)%p)%p;
        }
        cout<<ans<<endl;
        return 0;
    }
    
    点击查看重新计算代码
    const ll p=998244353;
    ll a[30],jc[(1<<15)+10],inv[(1<<15)+10],jc_inv[(1<<15)+10],sum[(1<<15)+10],f[2][(1<<15)+10],g[210];
    ll qpow(ll a,ll b,ll p)
    {
        ll ans=1;
        while(b)
        {
            if(b&1)  ans=ans*a%p;
            b>>=1;
            a=a*a%p;
        }
        return ans;
    }
    ll C(ll n,ll m,ll p)
    {
        return (n>=m&&n>=0&&m>=0)?jc[n]*jc_inv[n-m]%p*jc_inv[m]%p:0;
    }
    int main()
    {
    #define Isaac
    #ifdef Isaac
        freopen("game.in","r",stdin);
        freopen("game.out","w",stdout);
    #endif
        ll n,m,k,ans=0,s,i,j;
        cin>>n>>m;  jc[0]=jc_inv[0]=1;
        for(i=1;i<=n;i++)  cin>>a[i];
        for(i=1;i<=max(n,m);i++)
        {
            inv[i]=qpow(i,p-2,p);
            jc[i]=jc[i-1]*i%p;
            jc_inv[i]=jc_inv[i-1]*inv[i]%p;
        }
        for(s=0;s<(1<<n);s++)
        {
            for(i=0;i<n;i++)
            {
                if((s>>i)&1)  sum[s]+=a[i+1];
            }
        }
        f[0][0]=1;
        for(i=0;i<m;i++)
        {
            memset(f[(i+1)&1],0,sizeof(f[(i+1)&1]));
            for(s=0;s<(1<<n);s++)
            {
                if(i-sum[s]<0)  continue;
                f[(i+1)&1][s]=(f[(i+1)&1][s]+f[i&1][s]*inv[n-__builtin_popcount(s)]%p)%p;
                for(j=0;j<n;j++)
                {
                    if(((s>>j)&1)==0&&i-sum[s]>=a[j+1]-1)
                        f[(i+1)&1][s|(1<<j)]=(f[(i+1)&1][s|(1<<j)]+
                        f[i&1][s]*inv[n-__builtin_popcount(s)]%p*C(i-sum[s],a[j+1]-1,p)%p)%p;
                }
            }
        }
        for(s=0;s<(1<<n);s++)
        {
            if(m-sum[s]<0)  continue;
            memset(g,0,sizeof(g));
            g[0]=1;
            for(i=0;i<n;i++)
            {
                if(((s>>i)&1)==0)
                {
                    for(j=m-sum[s];j>=1;j--)
                    {
                        for(k=1;k<=min(j,a[i+1]-1);k++)  g[j]=(g[j]+g[j-k]*C(j,k,p)%p)%p;
                    }
                }
            }
            ans=(ans+f[m&1][s]*g[m-sum[s]]%p*__builtin_popcount(s)%p)%p;
        }
        cout<<ans<<endl;
        return 0;
    }
    

T2 B. 排序 40pts

  • 原题: Project Euler | 欧拉计划 Problem 524 First Sort II

  • 手模下较小数据下操作 1,2 的本质是将某个非前缀 max 的数 pi 消耗 2x 的次数使得将 pi 插入到其在 [1,i] 升序排序后的位置,其中 x 表示 [1,i1] 中比 x 小的数的个数。

  • 考虑按照 k 的二进制表示下从低到高的各位进行构造。

  • 以第 0 位为例,若 k 这一位为 0 那么此时必须放 1 ;否则必须放 2 ,但后续过程中 1 所在的位置就不确定了。

  • 1 对其他数的影响本质上是将其的贡献 ×2 ,故 k 某一位为 0 时可以将 1 塞进去从而进行拼接。

    点击查看代码
    stack<ll>s;
    int main()
    {
    #define Isaac
    #ifdef Isaac
        freopen("sorting.in","r",stdin);
        freopen("sorting.out","w",stdout);
    #endif
        ll k;
        cin>>k;
        for(ll x=1;k;k>>=1)
        {
            if(k%2==1)
            {
                s.push(x);  x++;
                cout<<x<<" ";
                x++;
            }
            else
            {	
                if(s.empty()==0)
                {
                    cout<<s.top()<<" ";
                    s.pop();
                }
                else
                {
                    cout<<x<<" ";
                    x++;
                }
            }
        }
        while(s.empty()==0)
        {
            cout<<s.top()<<" ";
            s.pop();
        }
        return 0;
    }
    

T3 C. 节日 0pts

总结

  • T1 误以为每种情况的概率相同,手摸了一整场的样例 2 也没模出来,破防了。
posted @   hzoi_Shadow  阅读(36)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2024-02-18 2024初三集训模拟测试1
扩大
缩小
点击右上角即可分享
微信分享提示