首页 > 其他分享 >uoj #770. 【UER #11】切割冰片

uoj #770. 【UER #11】切割冰片

时间:2022-11-21 21:58:49浏览次数:71  
标签:11 横线 覆盖 int res lsh uoj UER mod

https://uoj.ac/contest/79/problem/770

赛时睡了一觉后就会转化了/hsh

  1. 考虑这个竖线倘若存在第 \(i\) 条能发到 \(+\infty\),那么 \(i\) 之后的也一定能发到!

  2. 考虑每条横线“阻挡”了一段区间的竖线发到 \(+\infty\),那么横线阻挡的区间肯定不交,且它是一段一段的,也就是说,第 \(i\) 条横线阻挡的区间在第 \(j\) 条横线的前面,\(i<j\)。这个随便就能看出来了。

  3. 假如你用 \(n\) 条横线,覆盖了前 \(j\) 条竖线,那么第 \(j\) 条竖线之后的形状是一定的,因此你只要考虑前面有多少种形状即可。

  4. 一种不同的覆盖方案对应一种不同的形状,显然不存在相同的覆盖方案但能覆盖出不同的形状,也不存在不同的覆盖方案但能覆盖出相同的形状。

既然如此,不妨想到 \(dp(i,j)\) 表示前 \(i\) 条横线,覆盖了前 \(j\) 条竖线的方案数。转移的时候考虑当前这条横线做了多少次转移即可,注意需要看看是否当前横线能够覆盖得到,倘若覆盖不到的话,因为可以不覆盖,直接转移前面的即可。

60~80分记录

然后不难发现是一个前缀和选点的形式,也就是你要选若干点,单不降,且满足在其区间里,倘若不在其区间里,那么那一个只能跟上一个相等(即选空)

即问题变为,你要构造一个序列 \(a\),满足 \(a_i\ge a_{i-1}\),且 \(a_i\le L_i\),否则,即 \(a_i>L_i\),你需要满足 \(a_i=a_{i-1}\),求构造序列的方案数。实际意义即为每条横线要么不覆盖,要么覆盖它能覆盖的,且覆盖区间不交,单不降。

image

考虑按其右端点进行划分(不存在线段覆盖了某个区间的一部分)

那么你定义 \(dp(i,j)\) 为构造到第 \(i\) 个位置,\(a_i\) 在第 \(j\) 个区间内的方案数,显然你要枚举 \(k\),然后 \([k,i]\) 这部分的 \(a\) 都在第 \(j\) 个区间内,然后进行转移。

需要注意的是,那么你 \(a_{k-1}<a_{k}\) 了,所以一定要满足 \(L_k\ge R_j\),即能覆盖到第 \(j\) 个区间,否则那你就只能跟上一个取等得到 \(a_k\) 取当前这一个区间的值,然而你 \(a_{k-1}\) 已经钦定在上一个区间了。

然后考虑组合数即可,注意对于中途不满足 \(L_k\ge R_j\) 的你就让他跟上一个取等即可,也就是你现在要让满足的点形成单调不降序列。

构造双射求单调不降

然后问题变为计算一个很大的组合数作为转移系数,注意到 \(n,m\) 同时加 \(1\),你列一下就能 \(O(1)\) 求出这东西啦。

AC记录

#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define ADD(x,y) ((x)+(y)>=mod?(x)+(y)-mod:(x)+(y))
using namespace std;
const int mod=998244353;
const int N=505;
int dp[N][N],f[N][N],n,m,L[N],inv[1002],lsh[N],tot; 

int fpow(int x,int y) {
	int res=1; x%=mod;
	while(y) {
		if(y&1) res=1ll*res*x%mod;
		y>>=1; x=1ll*x*x%mod;
	} return res;
}

signed main() {
	cin.tie(0); ios::sync_with_stdio(false);
	inv[0]=1; for(int i=1;i<=1000;i++) inv[i]=fpow(i,mod-2);
	cin>>m>>n;
	for(int i=1;i<=n;i++) {
		cin>>L[i]; L[i]=min(L[i],m);
	}
	for(int i=1;i<=n;i++) lsh[++tot]=L[i];
	sort(lsh+1,lsh+1+tot); tot=unique(lsh+1,lsh+1+tot)-lsh-1;
//	for(int v=0;v<=tot;v++) {
//		for(int i=1;i<=n;i++) {
//			int res=0; 
//			for(int j=i;j<=n;j++) {
//				if(!v) {
//					cval[v][i][j]=1; continue ;
//				}
//				if(L[j]>=lsh[v]) ++res;
//				cval[v][i][j]=C(lsh[v]-lsh[v-1]+res-1,res);
//			}
//		}
//	}
	dp[0][0]=f[0][0]=1;
	for(int i=1;i<=tot;i++) f[0][i]=ADD(f[0][i-1],dp[0][i]);
	for(int i=1;i<=n;i++) {
		dp[i][0]=1;
		for(int j=1;j<=tot;j++) {
			if(L[i]<lsh[j]) {
				for(int k=j;k<=tot;k++) dp[i][k]=dp[i-1][k];
				break ;
			}
			int res=1,nn=lsh[j]-lsh[j-1]-1,mm=0;
			for(int k=i;k>=1;k--) {
				if(L[k]<lsh[j]) continue ;
				if(L[k]>=lsh[j]) {
					++nn; ++mm; res=res*nn%mod*inv[mm]%mod;
				}
//				int qwq=C(lsh[j]-lsh[j-1]+res-1,res);
				dp[i][j]=ADD(dp[i][j],1ll*f[k-1][j-1]*res%mod);
				if(dp[i][j]<0) dp[i][j]+=mod;
			}
//			dp[i][j]=f[i-1][j];
		}
		f[i][0]=dp[i][0];
		for(int j=1;j<=tot;j++) f[i][j]=ADD(f[i][j-1],dp[i][j]);
//		for(int j=0;j<=tot;j++) cout<<dp[i][j]<<' ';
//		cout<<'\n';
	}
	int ans=0;
	for(int i=0;i<=tot;i++) {
		ans=ADD(ans,dp[n][i]);
	}
	ans=(ans%mod+mod)%mod;
	cout<<ans;
	return 0;
} 

标签:11,横线,覆盖,int,res,lsh,uoj,UER,mod
From: https://www.cnblogs.com/xugangfan/p/16913486.html

相关文章

  • 110001 求最短距离已知两点坐标
    <?phpheader('Content-Type:text/html;charset=utf-8');define('ROOT',$_SERVER['DOCUMENT_ROOT']);includeROOT.'/assets/php/head.php';$tit='求最短距离已知......
  • 【题解】TEST 22.11.21 - 计数(感谢强大艾尔法!!1)
    我们要求的是:\[\begin{aligned}G(x)&=\sum_{i\geq0}(i+n-m)!(-1)^{m-i}x^i\\G'(x)&=\sum_{i\geq1}i(i+n-m)!(-1)^{m-i}x^{i-1}\end{aligned}\]考虑凑\(\sum\limits......
  • 2022.11.21
    咕了两天blog了,原因是都在颓废。P5410是\(Z\)函数的板子!它与\(KMP\)的思想差不多,同时我认为它更接近\(manacher\),都是由之前的转到当前的,再进行总复杂度\(\Thet......
  • 11-21 日鲜花 - Edit
    <metahttp-equiv="refresh"content="3;url=https://www.luogu.com.cn/blog/Junko-Youmu/e-d-i-t">这东西居然可以在博客园后台预览一个网页?厉害。原文:https://www.lu......
  • 11.21 模拟赛题解
    \(\textdistance\)简要题意给定一棵\(n\)个结点的无根树,每条边有一个边权,询问以哪一个点作为根时,到其他所有节点的距离之和最大。距离的定义为到该点最短路径上的边权......
  • DTOJ 2022-11-21 测试 题解
    测试成果非常寄35+56+0+8=99基本上把能犯的错误都犯了T1记得dp数组初始化\(-\infty\)!!!!T2记得认真暴搜,不要乱记录访问状态T3记得把调试删掉!!!!!T4记得开longlong......
  • ### 52ed 2022/11/19 模拟赛总结37
    这次并没有认真打,但是有一些问题还是。。。真令人无语地暴露了出来反思本次暴力T2时,看到题目说运算过程全在无符号32位整数内,很高兴地冒死用了unsignedint,然后输入输......
  • [题解] CF1149D Abandoning Roads
    难得自己想出来一道3000分的题,虽然说考试的时候打挂了...首先先对较小的边缩点,然后求连通块内的最短路。显然,连通块内其实想怎么走就怎么走,但不能走较大的边。然后不同......
  • 11.21.3
    #include<stdio.h>#include<math.h>intmain(){ inti; for(i=10;i<1000;i++) {if(i>=10&&i<100&&pow(i%10,3)+pow(i/10,3)==i)printf("%d ",i); if(i>=100&&i<100......
  • delphi D11编程语言手册 学习笔记(P225-P343) OOP(面向对象)
      这本书可以在Delphi研习社②群256456744的群文件里找到.书名:Delphi11AlexandriaEdition.pdf●P139类是抽象的,变量是类的具现.类在定义时,只是......