BZOJ4402 Claris的剑, 【2020六校联考NOIP #1】山水画

摘要:
主题来源:BZOJ4402 Claris的剑是后来选定的,主题是“memset0”。从我放入的括号中,不难看出,如果去掉每个值的第一个出现位置,它们必须是一个子序列。在其他地方,几个元组被插入到这个子序列中。如果您知道序列长度和最大元素,那么这样的序列的数量相当于将元素放入不同性质的(j-1)个框中。该框可以为空,方案数为。然后,答案可以写成:[egin{align}ext{ans}&=1+sum_{j=2}^{min(m,n)}sum_{k=0}^{lflourfrac{n-j}{2}floor}{k+j-2choosej-2}+sum_{j=2}^}min}sum_{k=0}^{lflour frac{{n-j-1}{2}floor}{k+j-2hoosej-2}&=1+sum_{j=0}^{2}地板+j}{kchoosej}+总和{j=0}^{min}总和{k=j}^}lflourfrac{n-j-3}{2}楼板+j}}{kchoose j}&=1+sum_{j=0}^{min}{lflourfrac{n-j-2}{2}地板+j+1chosej+1}+sum_{j=0}^{min}{lflourfrac{n-j3}{2}floor+j+1hoosej+1}结束{align}注:使用最后一步。x+MOD:x;}inlinevoiddd{x=mod1(x+y);}inlinevoid sub{x=mod2(x-y);}inlineintpow_ mod{inty=1;而{if(i&1)y=y*x%mod;x=x*x%mod;i˃˃=1;}returny;}intfac[MAXN+5]、ifac[MAXN+3];inlineintcomb{if(n<k)return0;returnfac[n]*ifac[k]%MOD*ifac[n-k]%MOD;}voidfacinit{fac[0]=1;forfac[i]=fac[i-1]*i%MOD,ifac[lim]=pow_MOD;forifac[i]=ifac[i+1]*(i+1)%MOD在j-1框中,对于{add;},可以为空}*/对于{add;}cou

题目来源:BZOJ4402 Claris的剑,后被选入【2020六校联考NOIP 第1场】,题为【山水画】,搬题人memset0。

算法:组合计数。

题目链接

“本质不同”这个要求比较毒瘤,我们必须先把它解决,以免重复计数。

发现每个数列,通过重新排列,一定能转化为如下两种形式之一:

  • (1,(2,1),(2,1),dots,2,(3,2),(3,2),dots,3,(4,3),(4,3),dots,j)
  • (1,(2,1),(2,1),dots,2,(3,2),(3,2),dots,3,(4,3),(4,3),dots,j,j-1)

其中(j)是序列里最大的数。

至于为什么所有数列一定能转化成这样,你只需要在知道每种值的出现次数以后,让字典序尽可能小,就一定会排成这个形式。

通过我打的括号,大家不难看出,如果把每种值第一次出现的位置拎出来,它们一定是一个恰为(1,2,dots ,j)的子序列(也就是序列里没有括号的部分)。而其它的位置,就是在这个子序列中,插入了若干个二元组。如果知道了序列长度(i)和最大元素(j),则这样的序列数量,就相当于把(lfloorfrac{i-j}{2} floor)个元素,放入(j-1)个本质不同的盒子,盒子可以为空,方案数是({lfloorfrac{i-j}{2} floor+j-1-1choose j-1-1})

注:把(x)个本质相同的物品放入(y)个本质不同的盒子,盒子可以为空。这个方案数可以用插板法求出。先在每个盒子里补一个物品,让所有盒子都不为空。然后插板,方案数是:({x+y-1choose y-1})

于是可以得到一个复杂度(O(nm))的做法:枚举(i,j),则答案是:

[ ext{ans}=1+sum_{i=2}^{n}sum_{j=2}^{min(m,i)}{lfloorfrac{i-j}{2} floor+j-2choose j-2} ]

其中最前面的(1),就是只有一个元素的序列({1}),为了避免组合数中出现负数,我们将其单独计算。

发现这个式子里,(i,j)纠缠在一起,很难直接计算。考虑枚举(k=lfloorfrac{i-j}{2} floor)的值。则答案又可以写成:

[egin{align} ext{ans}&=1+sum_{j=2}^{min(m,n)}sum_{k=0}^{lfloorfrac{n-j}{2} floor}{k+j-2choose j-2} +sum_{j=2}^{min(m,n-1)}sum_{k=0}^{lfloorfrac{n-j-1}{2} floor}{k+j-2choose j-2}\ &=1+sum_{j=0}^{min(m-2,n-2)}sum_{k=j}^{lfloorfrac{n-j-2}{2} floor+j}{kchoose j} +sum_{j=0}^{min(m-2,n-3)}sum_{k=j}^{lfloorfrac{n-j-3}{2} floor+j}{kchoose j}\ &=1+sum_{j=0}^{min(m-2,n-2)}{lfloorfrac{n-j-2}{2} floor+j+1choose j+1}+sum_{j=0}^{min(m-2,n-3)}{lfloorfrac{n-j-3}{2} floor+j+1choose j+1} end{align} ]

注:最后一步,是用到了(sum_{i=x}^{y}{ichoose x}={y+1choose x+1})。可以用杨辉三角形来理解:相当于求杨辉三角上连续若干行,每行的第(x)个数的和(画出来是一条斜向左下的斜线)。从上到下把每两个数合并为下一行的第(x+1)个数即可。也可以用组合意义来理解:从(y+1)个数里选(x+1)个数,枚举最后一个数在哪,然后在前面随便选。

通过预处理阶乘和逆元,求组合数是(O(1))的,因此最后的时间复杂度为(O(m))(n,m)同阶)。

参考代码:

//problem:BZOJ4402
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define mk make_pair
#define lob lower_bound
#define upb upper_bound
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;

template<typename T>inline void ckmax(T& x,T y){x=(y>x?y:x);}
template<typename T>inline void ckmin(T& x,T y){x=(y<x?y:x);}

const int MAXN=2e6;
const int MOD=1e9+7;
inline int mod1(int x){return x<MOD?x:x-MOD;}
inline int mod2(int x){return x<0?x+MOD:x;}
inline void add(int& x,int y){x=mod1(x+y);}
inline void sub(int& x,int y){x=mod2(x-y);}
inline int pow_mod(int x,int i){int y=1;while(i){if(i&1)y=(ll)y*x%MOD;x=(ll)x*x%MOD;i>>=1;}return y;}

int fac[MAXN+5],ifac[MAXN+5];
inline int comb(int n,int k){
	if(n<k)return 0;
	return (ll)fac[n]*ifac[k]%MOD*ifac[n-k]%MOD;
}
void facinit(int lim=MAXN){
	fac[0]=1;
	for(int i=1;i<=lim;++i)fac[i]=(ll)fac[i-1]*i%MOD;
	ifac[lim]=pow_mod(fac[lim],MOD-2);
	for(int i=lim-1;i>=0;--i)ifac[i]=(ll)ifac[i+1]*(i+1)%MOD;
}

int main() {
	facinit();
	int n,m;
	cin>>n>>m;
	int ans=1;
	/*
	for(int i=1;i<=n;++i){
		for(int j=2;j<=m && j<=i;++j){
			add(ans, comb((i-j)/2+j-1-1, j-1-1)); // (i-j)/2个东西,放进j-1个盒子,可以为空
		}
	}
	*/
	for(int j=0;j<=min(m-2,n-2);++j){
		add(ans, comb((n-j-2)/2+j+1, j+1));
	}
	for(int j=0;j<=min(m-2,n-3);++j){
		add(ans, comb((n-j-3)/2+j+1, j+1));
	}
	cout<<ans<<endl;
	return 0;
}

免责声明:文章转载自《BZOJ4402 Claris的剑, 【2020六校联考NOIP #1】山水画》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇idea在处理spring国际化解决中文乱码,properties的格式:native-to-ascii打印全排列下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

【转】QImage 图像格式小结

构造图像:,QImagemyImage1=QImage;根据文件名打开图像。如果图像本身是32位或24位,则程序中的图像是32位。如果图像本身是8位或1位,则程序中的对应图像是8位或者1位。宽度表示图像宽度,高度表示图像高度。...

【资料】2021年最网红的FPGA开发板之一——DE10-Nano (SOC FPGA入门推荐!)

DE10 Nano开发板是2021最受欢迎的FPGA开发板之一。除了广泛应用于物联网、边缘计算、硬件加速、AI和EDA教育课程之外,许多爱好者还在网络上日益流行的开源复古游戏项目Mister中使用它。让我们来看看DE10 Nano提供的材料:Youjing官方网站上的材料(中文手册可用!!!23~课程培训材料2018产学合作培训材料基于2018产学协作培训材...

Notepad++正则表达式查找替换文本中文字符

测试需求测试工具中xml配置文件中的注释字段包含中文字符。Win10系统中使用的工具中偶尔会出现中文乱码,导致配置文件无效。解决方案是将配置文件中的中文注释替换为英文注释,或者直接替换和删除。如何查找和删除配置文件中的汉字?“记事本”中使用正则表达式[^x00 xff]来匹配汉字。替换完成如下3。所有汉字已被替换。...

MySQL学习笔记:字符串前后补全0

遇到一个要求:如果位数小于6,则需要使用函数LPAD()和RPAD()自动完成6位。LPAD使用字符串padstr填充并完成左侧的str,直到其长度达到len个字符,并返回str。...

JavaMail给QQ邮箱发邮件报错

org.springframework.mail.MailAuthenticationException:身份验证失败;nestedexceptionisjavax.mail.AuthenticationFailedException:535错误:http://service.mail.qq.com/cgi-bin/help?subtype=1&&a...

bootstrap删除模态框弹出并询问是否删除【通用删除模态框】

divclass=“模态对话框”&gt;divclass=“modal header”&gt;spanaria hidden=“true”&gt;h4class=“模态标题”&gt;divclass=“modal body”&gt;divclass=“模态页脚”&gt;...