$bzoj1025-SCOI2009$游戏 群论 $dp$
题面描述
\(windy\)学会了一种游戏。对于\(1\)到\(N\)这\(N\)个数字,都有唯一且不同的1到N的数字与之对应。最开始\(windy\)把数字按顺序\(1,2,3,\cdots,N\)写一排在纸上。然后再在这一排下面写上它们对应的数字。然后又在新的一排下面写上它们对应的数字。如此反复,直到序列再次变为\(1,2,3,\cdots,N\)。 如:$ 1\ 2\ 3\ 4\ 5\ 6$ 对应的关系为 \(1\to 2\ 2\to 3\ 3\to 1\ 4\to 5\ 5\to 4\ 6\to 6\) ,\(windy\)的操作如下:
1 2 3 4 5 6
2 3 1 5 4 6
3 1 2 4 5 6
1 2 3 5 4 6
2 3 1 4 5 6
3 1 2 5 4 6
1 2 3 4 5 6
* 这时,我们就有若干排$1$到$N$的排列,上例中有$7$排。现在$windy$想知道,对于所有可能的对应关系,有多少种可能的排数。输入格式
- 包含一个整数\(N,1 \leq N \leq 10^3\)
输出格式
- 包含一个整数,可能的排数。
题解
- 在做此题前,建议各位先行了解群论及置换概念。
- 在了解置换的概念后,我们不难发现原题可以抽象为对于\(1\)~\(n\)的排列的所有可能置换 统计通过置换回到原排列的可能不同次数。
- 我们可以将置换写成循环节的形式,即\((a\ b\ c)(d\ e)(f)\),由循环节的性质得 通过该置换回到原排列的次数为\(lcm\)(各循环节长度)。
- 简单证明:
- 一个循环节最后回到自己需\(k*len\ (k\in N^*)\),\(len\)为循环节长度。
- 让所有循环节同时回到自己需\(lcm(len_1,\cdots,len_x)\),\(x\)为总循环节个数。
- 现在,我们把题意转化为求所有{\(a_m\)},使\(\sum_{i=1}^m a_i\)=n,求这样的数列的\(lcm(a_1,\cdots,a_m)\)的不同个数。
- 当你用当前结论做\(dp\)时,不难发现,你无论怎样\(dp\)都会重复计数。
- 我们考虑反过来做,当我们能得到\(lcm=\prod_{i=1}^k p_i\),要使得能得到该\(lcm\)的和最小的数列为,即\(a_i=p_i^r\)。
- 证明:可类比字符串中最小表示法,如此对于一个\(p_i\),我们有唯一表示其的方法。又因为质因数分解也是唯一的,因此对于\(lcm\),我们得到唯一表示其的数列。
- 然后,问题进一步转化为找到所有以质因数为数列,且\(s_n\leq n\)的数列个数,当\(s_n<n\)时余下的用长度为1的循环节代替。
- 这样,我们对所有\(p_i^1,p_i^2,\cdots,p_i^r\)做背包即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=1e3+4;
int pri[MAXN];
bool use[MAXN];
int n;
ll f[MAXN][MAXN];
int main(){
scanf("%d",&n);
for (int i=2;i<=n;i++){
if (!use[i]) pri[++pri[0]]=i;
for (int j=1;j<=pri[0]&&i*pri[j]<=n;j++){
use[i*pri[j]]=1;
if (i%pri[j]==0) break;
}
}
// cout<<pri[0]<<endl;
f[0][0]=1;
for (int i=1;i<=pri[0];i++){
for (int j=0;j<=n;j++) f[i][j]=f[i-1][j];
for (int j=pri[i];j<=n;j*=pri[i]){
for (int k=0;k<=n-j;k++){
f[i][j+k]+=f[i-1][k];
}
}
}
ll ans=0;
for (int i=0;i<=n;i++) ans+=f[pri[0]][i];
printf("%lld\n",ans);
return 0;
}
随机推荐
- C#事件订阅及触发例子
最典型的事件例子,猫叫了(事件源),老鼠跑了(事件订阅者),惊醒主人(事件订阅者) 源代码: class Program { static void Main(string[] args) { Cat ...
- Redis与Java的链接Jedis(二)
就像jdbc跟java链接数据库一样 redis跟java链接最好的工具就是Jedis 相关资源下载:https://github.com/xetorthio/jedis 正常建立java项目, 导入 ...
- iBeacon的第一篇(基于Swift实现)
低功耗蓝牙技术现在几乎是只能手机的标配.随着这一技术的发展,苹果在2013年WWDC大会上,苹果推出iBeacon技术.该技术允许开发人员开发能够使用iBeacon硬件传感器的iOS应用程序,来为相应 ...
- 编写高质量代码改善C#程序的157个建议——建议70:避免在调用栈较低的位置记录异常
建议70:避免在调用栈较低的位置记录异常 并不是所有的异常都要被记录到日志,一类情况是异常发生的场景需要被记录,还有一类就是未被捕获的异常.未被捕获的异常通常被视为一个Bug,所以,对于它的记录,应该 ...
- Crystal Report保留小数位
If IsNull({DECL_INV_ITEM_I.DECLEAR_NO}) Or Trim({DECL_INV_ITEM_I.DECLEAR_NO}) = "" Then &q ...
- uwsgi启动报错WARNING: Can't find section "uwsgi" in INI configuration file autotestsite_uwsgi.ini
提示配置文件头部找不到 [uwsgi] 解决: 在最上方加上[uwsgi],有时候明明有标识,但是还是提示,那就再加一个
- C# 编写的SqlServer 数据库自动备份服务,带配置,功能强大
数据库自动备份服务,带配置,还算可以吧 周末抽时间,编写了一个这样的工具,可以让,对数据库不了解或不熟悉的人,直接学会使用备份,省时省力,同样,我也将一份,通过脚本进行备份的,也奉献上来, 通过sql ...
- c#中关于协变性和逆变性(又叫抗变)帮助理解
今天回忆了之前看的<深入理解C#>这本书中的泛型章节,其中对泛型的可变性的理解.泛型可变性分两种:协变和逆变.逆变也又称为抗变. 怎么理解这两个名词的意思: ①:协变即为在泛型接口类型中使 ...
- asp.net mvc+webuploader大文件分片上传
首先是前端: var GUID = WebUploader.Base.guid();//一个GUID uploadereditsVideo = WebUploader.create({ // swf文 ...
- WordCloud 简介
WordCloud 简介 GitHub GitHub:https://github.com/amueller/word_cloud example:https://github.com/amuelle ...