首页 > 其他分享 >12.17 CW 模拟赛 T4. 记忆碎片

12.17 CW 模拟赛 T4. 记忆碎片

时间:2024-12-17 21:44:33浏览次数:3  
标签:mathbb SZ int T4 12.17 cdot MOD CW nowS

思路

转化题意, 问你在一个带权无向完全图中, 如何填上 \(w_i \in \left[1, \frac{n \cdot (n - 1)}{2} \right]\) , 使得其最小生成树上的边权为给定的 \(n - 1\) 个数

考虑模仿 \(\rm{kruskal}\) 的方式, 令 \(f_S\) 表示当前点集为 \(S\) , 每次转移, 如果当前边权需要在最小生成树中, 我们考虑连不联通的两点, 否则连联通的两点

这样只能通过 \(30 \%\) 的点

考虑优化

注意到我们其实不需要按照边来存储状态, 我们只需要知道连通块的大小即可, 考虑构造一种状态集合 \(\mathbb{S} = \{ (i, SZ_i) \}\) 表示大小为 \(SZ_i\) 的连通块有 \(i\) 个, 要求 \(\displaystyle \sum_{i = 1}^{\lvert \mathbb{S} \rvert} i \cdot SZ_i = n\)

这样我们对于每条树边才需要转移, 因为非树边不会对状态有影响

你发现状态的连通块个数顶多只有 \(\sqrt{n}\) 种, 再 \(\mathcal{O} (\sqrt{n})\) 求出变化后的状态, 需要转移 \(n\) 次, 枚举状态数 \(\mathcal{O} (n \mathop{P} (n))\) , 其中 \(\mathop{P} (n)\) 为分拆数
总时间复杂度 \(\mathcal{O} (n^2\sqrt{n}\mathop{P} (n))\) , 我认为可以通过

总结一下, 我们令 \(f_{i, \mathbb{S}}\) 表示考虑到第 \(i\) 条边, 当前的连通块状态为 \(\mathbb{S}\) 时的方案数, 令树边集合为 \(\mathbb{V}\)

\[f_{i, \mathbb{S}} = \begin{cases} \begin{aligned} & \sum_{a, b} \{ f_{i - 1, \mathbb{S}_{pre} } + SZ_a \cdot SZ_b , i \in \mathbb{V} \} \\ & f_{i - 1, \mathbb{S} } \cdot \sum_{j = 1}^{\lvert \mathbb{S} \rvert} \frac{SZ_j \cdot (SZ_j - 1)}{2} \end{aligned} \end{cases} \]

当然具体实现中使用刷表法

实现

框架

首先你至少要把状态预处理出来, 然后就按照树边和非树边干就完了

代码

#include <bits/stdc++.h>
const int MAXM = 41 * 41;
const int MAXP = 37400;
const int MOD = 1e9 + 7;

int add(int a, int b) { return (a + b >= MOD) ? a + b - MOD : a + b; }
int dec(int a, int b) { return (a - b < 0) ? a - b + MOD : a - b; }
int mul(int a, int b) { return (1LL * a * b) % MOD; }
void pluson(int &a, int b) {a = add(a, b);}


int n;
bool V[MAXM];

std::map<std::vector<int>, int> S;
std::map<int, std::vector<int>> Sback;

std::vector<int> nowS, Snext;
int id = 0;
int C[MAXP];
void init(int x, int v){
	if(v == 0) {
		if(x == 0) {
			S[nowS] = ++id, Sback[id] = nowS;
			for(int i = 0; i < nowS.size(); i++) C[id] += nowS[i] * (nowS[i] - 1) / 2;
		}
		return ;
	}

	init(x, v - 1);
	if(x >= v){
		nowS.push_back(v);
		init(x - v, v);
		nowS.pop_back();
	}
}

int f[MAXM][MAXP];

int main()
{
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int read; scanf("%d", &read);
        V[read] = true;
    }
    int m = n * (n - 1) / 2;
    
    /*初始化状态*/
    init(n, n);

    f[0][1] = 1;
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= id; j++)
            if (f[i - 1][j]) {
                if (V[i]) {
                    nowS = Sback[j];
                    for (int a = 0; a < nowS.size(); a++)
                        for (int b = a + 1; b < nowS.size(); b++) {
                            Snext.clear();
                            Snext.push_back(nowS[a] + nowS[b]);
                            for (int k = 0; k < nowS.size(); k++)
                                if (k != a && k != b)
                                    Snext.push_back(nowS[k]);
                            std::sort(Snext.begin(), Snext.end());
                            std::reverse(Snext.begin(), Snext.end());
                            pluson(f[i][S[Snext]], mul(f[i - 1][j], mul(nowS[a], nowS[b])));
                        }
                }
                else
                    pluson(f[i][j], mul(f[i - 1][j], C[j] - i + 1));
            }

    int Ans = 0;
    for (int i = 1; i <= id; i++)
        pluson(Ans, f[m][i]);
    printf("%d", Ans);


    return 0;
}

总结

善于模仿算法的实现方式

优化状态, 首先找到算法的本质, 然后只存储需要用到的性质, 本题中利用组合数学简化了一些状态, 具体的, 连边这一类问题, 通过连通块的组合数即可求出

标签:mathbb,SZ,int,T4,12.17,cdot,MOD,CW,nowS
From: https://www.cnblogs.com/YzaCsp/p/18613459

相关文章

  • 12.17随笔
    这里是12.17随笔UML图绘制--类图:https://blog.csdn.net/Qhx20040819/article/details/132268512?ops_request_misc=%257B%2522request%255Fid%2522%253A%252238d718ecb9472f600fa9689ab6e986fb%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=38d......
  • java面试问题(2024.12.17)
    记录java岗面试问题对java的了解Java是一门面向对象的编程语言,吸收了C++语言中大量的优点,但又抛弃了C++中容易出错的地方,如垃圾回收。Java又是一门平台无关的编程语言,通过java虚拟机(jvm)可以实现一次编译,处处运行。对jvm的了解Java虚拟机,是Java实现跨平台的关键所......
  • 12.17日报
    今天完成软件案例分析实验,以下为部分实验内容:packagecom.gdpu.controller;importcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper;importcom.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;importcom.baomidou.mybatisplus.core.metadata.......
  • PVE系统下——OpenWRT一键扩容脚本(x86下EXT4&SquashFS)
    扩容了x86上的OpenWrt根分区和文件系统。1.PVE上增加硬盘大小2.执行脚本安装依赖opkgupdateopkginstallpartedlosetupresize2fs下载脚本并一键执行wget-U""-Oexpand-root.sh"https://openwrt.org/_export/code/docs/guide-user/advanced/expand_root?......
  • 【人工智能】教你如何利用CodeMoss的OpenAI API调用GPT4大语言模型(最全教程)
    文章目录OpenAIAPIKey的使用场景步骤1:打开[CodeMoss](https://pc.aihao123.cn/index.html#/page/login?invite=1141439&fromChannel=1_Moss1213)工具步骤2:进入API管理界面步骤3:生成新的OpenAIAPI使用OpenAIAPI的实战教程1.可以调用的模型2.Python示例代码(基础)3.Pytho......
  • 【Python+Flask+OpenAI】利用OpenAI API Key实现GPT4-智能AI对话接口demo - 从0到1手
    文章目录前言环境准备安装必要的库生成OpenAIAPI代码实现详解导入必要的模块创建Flask应用实例配置OpenAIAPI完整代码如下(demo源码)代码解析利用Postman调用接口了解更多AI内容结尾前言Flask作为一个轻量级的PythonWeb框架,凭借其简洁易用的特点,成为构建Web应用......
  • 12.12 CW 模拟赛 T3. 消除贫困
    思路朴素容易发现一个人资金变化是这样的:对于\(op=1\)的情况,会将其直接变成\(x\)对于\(op=2\)的情况,将其变成\(\max(x,当前值)\)直接用线段树暴力的维护即可巧妙容易发现\(op=2\)相当于一个大保底,我们先倒着处理出每个人到\(i\)位置至少有多少......
  • 12.12 CW 模拟赛 T1. 理想路径
    前言作为一个别的不行抗伤无敌的\(\rm{man}\),区区反向\(\rm{rk\1}\)不足为惧\(\rm{HD0X}\)巨佬场切\(2700\),\(\%\%\%\)思路朴素先把考场上一些基础的想法搬过来考虑一个环什么时候会导致产生字典序负环,这个好像还比较显然,就是如果出去的那个点的字典序小......
  • acwing 1141. 局域网
    某个局域网内有 nn 台计算机和 kk 条 双向 网线,计算机的编号是 1∼n1∼n。由于搭建局域网时工作人员的疏忽,现在局域网内的连接形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成网络卡的现象。注意:对于某一个连接,虽然它是双向的,但我们不将其当做......
  • 12.10 CW 模拟赛 T3. 循环
    算法很容易想到枚举短边断环之后\(\mathcal{O}(P)\)的求答案那么这个算法还有前途吗?可以发现,对于每次枚举断边,断\((i,i+1)\)和\((i-1,i)\)这两条边,变化量并不大,严格来说,均摊复杂度\(\mathcal{O}(P)\)具体实现上怎么处理呢?将断第\(x\)条边作为横......