您的位置:首页 > 其它

BZOJ1025: [SCOI2009]游戏

2014-02-28 11:59 169 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=1025

Description

windy学会了一种游戏。对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应。最开始windy把数字按顺序1,2,3,……,N写一排在纸上。然后再在这一排下面写上它们对应的数字。然后又在新的一排下面写上它们对应的数字。如此反复,直到序列再次变为1,2,3,……,N。 如: 1 2 3 4 5 6 对应的关系为 1->2 2->3 3->1 4->5 5->4 6->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想知道,对于所有可能的对应关系,有多少种可能的排数。

1 <= N <= 1000 。

首先一个对应关系的排数就是一个置换里面每一个联通块大小的LCM,所以问题转化成了:

把一个数N,拆分成若干个数A1,A2,A3....,使得A1+A2+A3..=N

求LCM{A1,A2,A3..}的不同数值个数。

若一个数A=a1^p1*a2^p2... 那这个数是划不来的,因为LCM=a1^max{p1}*a2^max{p2}...

A=a1^p1*a2^p2,若这里面的p1,p2都是最大的,那对LCM的贡献和 B=a1^p1, C=a2^p2 是一样的。

但是B+C<B*C=A,所以把A分解成B和C是完全更优的。

所以一个数肯定是一个单一质数的幂次方。

所以现在的问题又简化成了这样:

Ax=ax^px

A1+A2+A3..≤N

a1,a2,a3都是定值,就是小于N的质数。

求满足条件的{p}数列的方法总数。

然后很神奇的转化成了背包的问题。

有点像什么今明的设呢懂洗。

ax只能选一次

所以对于每个Ax=ax^p 分别来做一遍再把两个数组合起来。。什么的。

f[i]表示A1+A2+..=i的时候的方法数

f[i]+=f[i-Ai]

#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
#define per(i,r,l) for (int i=r;i>=l;--i)
typedef long long LL;
const int MAX_N=1050;
int prime[MAX_N],top;
int n;
void Prep(){
rep(i,2,n){
bool flag=0;
for (int j=2;j*j<=i;++j) if (i%j==0){flag=true;break;}
if (!flag) prime[++top]=i;
}
}
LL f[MAX_N][MAX_N];
void DP(){
rep(i,0,top) f[i][0]=1;
rep(i,1,top){
for (int j=prime[i];j<=n;j*=prime[i])
per(k,n,j) f[i][k]+=f[i-1][k-j];
rep(j,1,n) f[i][j]+=f[i-1][j];
}
LL res=0;
rep(i,0,n) res+=f[top][i];
printf("%lld\n",res);
}
int main(){
scanf("%d",&n);
Prep();
DP();
}

注重把实际问题转化为数学模型!通过数学模型推导分析!这相当重要!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: