首页 > 其他分享 >冲刺国赛模拟 32

冲刺国赛模拟 32

时间:2023-07-07 20:57:09浏览次数:61  
标签:32 back 冲刺 second del 国赛 front dp first

玄学。

赛时以为 \(O(mn^22^n),m=200,n=15\) 拿头跑 \(2s\),结果题解甚至 \(m3^n\) 跑过……蚌埠了。

首先你发现题目要求保留边使得连通的方案数。发现这玩意和 \(\ln\) 长得类似,于是设 \(g_S\) 为一个 \(m\) 次多项式,\(g_{i,S}\) 为 \(S\) 导出子图内选 \(i\) 条边方案,然后取个 \(\ln\) 就得到答案,复杂度 \(O(m^2n^22^n)\),插点值算可以做到 \(O(mn^22^n)\),不知道怎么过的。

由于有重边自环,所以懒得写了,贺了份 \(m3^n\) 的,更不知道怎么过的,而且跑的还挺快。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int mod=1000000007;
int n,m,jc[210],inv[210];
int C(int n,int m){
    if(n<m||m<0)return 0;
    return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
vector<int>g[20];
int size[1<<15],tmp[20],dp[1<<15][210],f[210][210];
int main(){
    scanf("%d%d",&n,&m);jc[0]=inv[0]=inv[1]=1;
    for(int i=2;i<=m;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1;i<=m;i++)jc[i]=1ll*jc[i-1]*i%mod,inv[i]=1ll*inv[i-1]*inv[i]%mod;
    for(int i=1;i<=m;i++){
        int u,v;scanf("%d%d",&u,&v);
        if(u==v){
            size[1<<u]++;tmp[u]++;
        }
        else g[u].push_back(v),g[v].push_back(u);
    }
    for(int s=1;s<(1<<n);s++){
        int x=__lg(s&-s);
        size[s]=size[s^(s&-s)]+tmp[x];
        for(int v:g[x]){
            if((s>>v)&1)size[s]++;
        }
    }
    for(int i=0;i<=tmp[0];i++)dp[0][i]=C(tmp[0],i);
    for(int s=1;s<(1<<n-1);s++){
        int k=size[s<<1|1];
        for(int i=0;i<=k+1;i++){
            for(int j=0;j<=k+1;j++)f[i][j]=0;
        }
        for(int t=s&(s-1);t;t=s&(t-1)){
            for(int i=0;i<=size[t<<1|1];i++)f[i][size[(s^t)<<1]]=(f[i][size[(s^t)<<1]]+dp[t][i])%mod;
        }
        for(int i=0;i<=size[1];i++)f[i][size[s<<1]]=(f[i][size[s<<1]]+dp[0][i])%mod;
        for(int i=0;i<=k;i++){
            for(int j=k;j>=1;j--){
                f[i+1][j-1]=(f[i+1][j-1]+f[i][j])%mod;
                f[i][j-1]=(f[i][j-1]+f[i][j])%mod;
            }
        }
        for(int i=1;i<=k;i++)dp[s][i]=(C(k,i)-f[i][0]+mod)%mod;
    }
    for(int i=n-1;i<=m;i++)printf("%d ",dp[(1<<n-1)-1][i]);puts("");
    return 0;
}

神奇的 dp 构造题。

考虑 \(a\) 的差分 \(c\),那么 \(b_i=\max(|c_i|,|c_{i+1}|,|c_i+c_{i+1}|)\)。设 \(dp_{i,x}\) 为考虑前 \(i\) 个,\(|c_i|=x\) 是否合法。转移考虑填入 \(c_{i+1}\) 的三种情况:

  1. \(|c_i|=b_i\):需要 \(|c_{i+1}|\le b_i\)。
  2. \(|c_{i+1}|=b_i\):只要有个 \(c_i\) 就行。
  3. \(|c_i+c_{i+1}|=b_i\):\(|c_{i+1}|=b_i-|c_i|\)。

那么发现 dp 的合法部分一定是由一个区间和若干单点组成。前两个操作可以变成删除一个前缀或后缀,第三个是先把整个区间翻转,然后平移 \(b_i\)。于是区间可以直接记录下来。单点的话可以用上个双端队列维护。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <list>
#define int long long
using namespace std;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,B,b[1000010],ans[1000010],lz[1000010];
pair<int,int>dp[1000010],del[1000010];
vector<int>v[1000010],fr[1000010],bk[1000010];
list<int>q;
signed main(){
    scanf("%lld%lld",&n,&B);
    for(int i=1;i<=n-2;i++)scanf("%lld",&b[i]);
    for(int i=0;i<=n-2;i++)del[i]=make_pair(1,0);
    dp[0]=make_pair(0,inf);
    for(int i=1;i<=n-2;i++){
        if(dp[i-1].first<=b[i]&&dp[i-1].second>=b[i]){
            dp[i]=make_pair(0,b[i]);
            while(!q.empty())v[i].push_back(q.front()),q.pop_front();
            continue;
        }
        while(!q.empty()&&q.front()*del[i-1].first+del[i-1].second>b[i])fr[i].push_back(q.front()),q.pop_front();
        while(!q.empty()&&q.back()*del[i-1].first+del[i-1].second>b[i])bk[i].push_back(q.back()),q.pop_back();
        if(!q.empty()&&(q.front()*del[i-1].first+del[i-1].second==b[i]||q.back()*del[i-1].first+del[i-1].second==b[i])){
            dp[i]=make_pair(0,b[i]);
            while(!q.empty())v[i].push_back(q.front()),q.pop_front();
            continue;
        }
        if(del[i-1].first)del[i]=make_pair(-del[i-1].first,b[i]-del[i-1].second);
        else del[i]=make_pair(-1,b[i]);
        if(q.empty()&&dp[i-1].first>b[i]){
            puts("NO");return 0;
        }
        dp[i]=make_pair(b[i]-min(dp[i-1].second,b[i]),b[i]-dp[i-1].first);
        if(dp[i-1].first>b[i])dp[i]=make_pair(inf,inf);
        if(dp[i].second!=b[i]&&(q.empty()||(q.front()*del[i].first+del[i].second!=b[i]&&q.back()*del[i].first+del[i].second!=b[i]))){
            if(q.empty()){
                q.push_back((b[i]-del[i].second)*del[i].first);
                lz[i]=1;
            }
            else{
                if(q.front()*del[i].first+del[i].second>q.back()*del[i].first+del[i].second){
                    q.push_front((b[i]-del[i].second)*del[i].first);
                    lz[i]=-1;
                }
                else{
                    q.push_back((b[i]-del[i].second)*del[i].first);
                    lz[i]=1;
                }
            }
        }
    }
    puts("YES");
    ans[n-1]=dp[n-2].first;
    if(!q.empty())ans[n-1]=min(ans[n-1],min(q.front()*del[n-2].first+del[n-2].second,q.back()*del[n-2].first+del[n-2].second));
    for(int i=n-2;i>=1;i--){
        if(lz[i]>0)q.pop_back();
        if(lz[i]<0)q.pop_front();
        if(v[i].size()){
            q.clear();
            for(int x:v[i])q.push_back(x);
        }
        if((dp[i-1].first<=b[i]&&dp[i-1].second>=b[i])||(!q.empty()&&(!q.empty()&&(q.front()*del[i-1].first+del[i-1].second==b[i]||q.back()*del[i-1].first+del[i-1].second==b[i])))){
            ans[i]=ans[i+1];
            if(ans[i+1]<ans[i+2])ans[i]+=b[i];
            else ans[i]-=b[i];
            while(!fr[i].empty())q.push_front(fr[i].back()),fr[i].pop_back();
            while(!bk[i].empty())q.push_back(bk[i].back()),bk[i].pop_back();
            continue;
        }
        while(!fr[i].empty())q.push_front(fr[i].back()),fr[i].pop_back();
        while(!bk[i].empty())q.push_back(bk[i].back()),bk[i].pop_back();
        int x=abs(ans[i+1]-ans[i+2]),y;
        if(x!=b[i])y=b[i]-x;
        else y=min(dp[i-1].first,min(q.front()*del[i-1].first+del[i-1].second,q.back()*del[i-1].first+del[i-1].second));
        ans[i]=ans[i+1]+(((x!=b[i])^(ans[i+1]<ans[i+2]))?y:-y);
    }
    int mn=inf;
    for(int i=1;i<=n;i++)mn=min(mn,ans[i]);
    for(int i=1;i<=n;i++)printf("%lld ",ans[i]-mn);puts("");
    return 0;
}

对。这玩意 std 不压行 9k,意见是不要改。

标签:32,back,冲刺,second,del,国赛,front,dp,first
From: https://www.cnblogs.com/gtm1514/p/17536018.html

相关文章

  • CH32V003使用ADC八通道转换注意事项
    本文以CH32V003_F4P6(20Pin)为模板 1、PA1、PA2为外部晶振输入引脚,同时也是ADC的CH1与CH0,所以需要先在system_ch32v00x.c文件中更改为内部48M的宏即可。注:CH32V003的ADC数据寄存器为10,通道转换值为[0-1024],精度为VCC/1024,VCC与外部参考电压相同[2.8-5.5]  2、ADC初......
  • 2532. 过桥的时间 todo
    共有k位工人计划将n个箱子从旧仓库移动到新仓库。给你两个整数n和k,以及一个二维整数数组time,数组的大小为kx4,其中time[i]=[leftToRighti,pickOldi,rightToLefti,putNewi]。一条河将两座仓库分隔,只能通过一座桥通行。旧仓库位于河的右岸,新仓库在河的左岸。开......
  • BZOJ 3223: Tyvj 1729 文艺平衡树 splay
    3223:Tyvj1729文艺平衡树TimeLimit: 10Sec  MemoryLimit: 128MBSubmit: 4614  Solved: 2699[Submit][Status][Discuss]Description您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列......
  • STM32IO口模拟IIC时序
    正点原子IIC讲解:https://www.bilibili.com/video/BV1o8411n7o9/?spm_id_from=333.337.search-card.all.click&vd_source=e35b16eeaf19ae2b23ff9587a735ee20一、IIC总线1.物理层(1)支持多设备,一个IIC通讯总线中可以连接多个IIC设备,支持多个通讯主机及多个通讯从机;(2)两条线:双......
  • python wincon32 word复制
    defword_copy(f1,f2):app=win32com.client.Dispatch('Word.Application')#打开word,经测试要是绝对路径doc=app.Documents.Open(f1)#复制word的所有内容doc.Content.Copy()#关闭worddoc.Close()word=win32com.client.Dispatc......
  • STM32下USB的使用
    一、介绍USB,即通用串行总线(UniversalSerialBus),包括USB协议和USB硬件两个方面,支持热插拔功能USB2.0使用四根线:VCC(5V)、GND、D+(3.3V)和D-(3.3V)(注:五线模式多了一个DI脚用于支持OTG模式,OTG为USB主机+USB设备双重角色)在USB主机上,D-和D+都接15K的电......
  • 正点原子内存管理实验室,keil mdk 和stm32cubeide gcc的函数替换
    https://www.cnblogs.com/RegressionWorldLine/p/11968467.html转载记录下 STM32.ld链接文件分析及一次bug解决过程问题描述原子板的代码中含有一个关于使用外部SRAM的功能,由于本人的开发板的SRAM只有512K,因此稍微修改了一下代码,同时使用GCC进行编译,但是这里却报错了,源码如......
  • mysql版本升级,升级成为8.0.32
    一、升级的方式和注意事项 1、同版本升级 简称本地升级 高版本数据库挂载低版本数据库数据实现升级2、升级注意事项  备份关键数据库文件 备份指定数据库的指定表数据二、部署Mysql5.6数据库,在Mysql5.6创建数据库名字data,创建表student设计表结构,插入个人记录和两条......
  • 基于DirectX11+ImGui的Win32桌面程序开发
    一、常见图形界面框架(DirectUI、GUI)1.题外话,纯属扯O举两个常用的开发框架,MFC和QtWidget里面每个控件都是Window,这是和DirectUI最大的区别。下面简单梳理下这个DirectUI与GUI之前错综复杂的爱恨情仇:1.在侏罗纪时期,传统的Handle式GUI框架,是由操作系统内核(win32k.sys)直......
  • STM32F10x 模拟空调内外机通讯
    1)内机为主 发送3A8000DB后由SMT32转成PWM0011101000010000000006ms为高        22ms   为低          46ms   为导码    2)外机为辅 收到内机发的PWM后,返加对就应的波形,同时将收到的波形加在前面。   ......