Problem

CF1528B Kavi on Pairing Duty

题目大意:

在数轴上有 \(2n\) 个点,相邻两个点的距离为 \(1\)。现在要将这些点两两匹配成 \(n\) 个圆弧,要求任意两个圆弧要么等长,要么其中一个包含另一个,问方案数。

Solution

首先观察发现好像合法的匹配一定是若干层包含,里面一层并列,也就是这个样子:

中间三个句号表示剩下的点组成的圆弧都是等长的。

然后发现被样例 Hack 了:

观察发现被 Hack 的原因是可能有若干个等长的圆弧相交,剩下比他们小的圆弧在他们相交的部分中。

于是尝试修改结论:合法的匹配一定是外面若干层,每一层都是若干个等长的圆弧,最里面一层为若干个等长的圆弧。

接下来考虑统计答案,可以把外面的几层与最内层分开统计。

首先考虑外面几层。
对于每一层,发现唯一合法的匹配长这个样子:

所以假设外面几层总共有 \(k\) 层,则外面几层的方案数相当于将 \(k\) 个数分成若干个区间的方案。
这个东西相当于要在 \(k-1\) 个空隙中插入若干个隔板的方案数。发现每个空隙都有插或不插两种选项,所以方案数为 \(2^{k-1}\)

然后考虑最内层。
由于每个圆弧要等长,所以假设要匹配 \(l\) 个圆弧,则每个圆弧的长度必须是 \(l\) 的因数。而对于每一确定的长度,则有唯一对应的一种匹配的方案。所以内层的方案数为 \(\operatorname{d}(l)\)

所以整个题目的答案就是:

\[\sum\limits_{i=1}^n (\operatorname{d}(i) \times 2^{n-i-1}) \]

Code

//Think twice,code once.
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int mod=998244353;

int n,f[1000005],pw[1000005];
long long ans;

int main() {
	scanf("%d",&n);
	pw[0]=1;
	for (int i=1;i<=n;i++) pw[i]=2*pw[i-1]%mod;//pw[i] 表示 2^i
	for (int i=1;i<=n;i++)
		for (int j=i;j<=n;j+=i) f[j]++;//f[j] 表示 j 的因数个数。
	for (int i=1;i<=n;i++) ans=(ans+(long long)pw[max(n-i-1,0)]*f[i]%mod)%mod;//统计答案。
	printf("%lld\n",ans);
	return 0;
}

原文地址:http://www.cnblogs.com/mk-oi/p/CF1528B.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性