【BZOJ】【1025】【SCOI2009】游戏
DP/整数拆分
整个映射关系可以分解成几个循环(置换群的预备知识?),那么总行数就等于各个循环长度的最小公倍数+1(因为有个第一行的1~N)。那么有多少种可能的排数就等于问有多少种可能的最小公倍数。
呃现在问题就变成了:给你一个数N,将它分解成几个数的和,然后找这些数的最小公倍数总共多少种。很明显又要找质数了>_>。
可以发现只要找循环长度(即拆出来的数)是质数的幂的情况就可以了,因为像6=2*3这种情况,我们可以用2和3来代替,又由于对于正整数来说,和$\leq$积,所以所有的非质数幂的情况都可以用质数幂的情况来表示/代替。(取一个6等于取2和3)
这个枚举总共有多少种分拆方案……我是用DP来实现的(没办法,dfs会TLE)
令$f[i][j]$表示用前 i 种质数的幂拼出 j 的方案数,那么$ans=\sum_{j=1}^n f[tot][j]$ tot为小于等于n的质数的数量。
转移也很简单啦~我的方法是从当前节点去更新其他节点的递推……写的可能有点奇怪……
f[i][j]可以转移到:f[i+1][j]和f[i+1][j+k] $(k=prime[i+1]^t)$ 呃……好像说的不太清楚……看我代码吧>_<不过我开了滚动数组……
/**************************************************************
Problem: 1025
User: Tunix
Language: C++
Result: Accepted
Time:20 ms
Memory:828 kb
****************************************************************/ //BZOJ 1025
#include<cstdio>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;++i)
using namespace std;
typedef long long LL;
const int N=;
int n,prime[N],tot;
LL f[][N],ans;
bool vis[N];
void getprime(int n){
F(i,,n){
if (!vis[i]) prime[++tot]=i;
F(j,,tot){
if (i*prime[j]>n) break;
vis[i*prime[j]]=;
if (i%prime[j]==) break;
}
}
}
int main(){
scanf("%d",&n);
getprime(n);
f[][]=;
for(int i=;i<tot;i++){
int now=i&;
F(j,,n) f[now^][j]=;
F(j,,n){
f[now^][j]+=f[now][j];
for(int k=prime[i+];k+j<=n;k*=prime[i+])
f[now^][j+k]+=f[now][j];
}
}
F(j,,n) ans+=f[tot&][j];
printf("%lld\n",ans+);
return ;
}
P.S.我一开始想的其实是$ans=\sum_{i=1}^{tot} \sum_{j=1}^n f[i][j]$ 所以转移的时候就不是从f[i]转移到f[i+1]了……而是转移到所有的$f[t][j+k](t>i)$所以时间复杂度更高,后来写题解的时候才突然想到这个更好理解&好写的代码……
/**************************************************************
Problem: 1025
User: Tunix
Language: C++
Result: Accepted
Time:368 ms
Memory:4796 kb
****************************************************************/ //BZOJ 1025
#include<cstdio>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
using namespace std;
typedef long long LL;
const int N=;
int n,prime[N],tot,f[N][N];
LL ans;
bool vis[N];
void getprime(int n){
F(i,,n){
if (!vis[i]) prime[++tot]=i;
F(j,,tot){
if (i*prime[j]>n) break;
vis[i*prime[j]]=;
if (i%prime[j]==) break;
}
}
}
int main(){
scanf("%d",&n);
getprime(n);
f[][]=;
rep(i,tot) F(j,,n){
F(t,i+,tot)
for(int k=prime[t];j+k<=n;k*=prime[t])
f[t][j+k]+=f[i][j];
}
F(i,,tot) F(j,,n) ans+=f[i][j];
printf("%lld\n",ans+);
return ;
}
(一开始的奇怪做法)
1025: [SCOI2009]游戏
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 1436 Solved: 900
[Submit][Status][Discuss]
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想知道,对于所有可能的对应关系,有多少种可能的排数。
Input
包含一个整数,N。
Output
包含一个整数,可能的排数。
Sample Input
3
【输入样例二】
10
Sample Output
3
【输出样例二】
16
HINT
【数据规模和约定】
100%的数据,满足 1 <= N <= 1000 。
Source
【BZOJ】【1025】【SCOI2009】游戏的更多相关文章
- BZOJ 1025 [SCOI2009]游戏
1025: [SCOI2009]游戏 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1533 Solved: 964[Submit][Status][ ...
- BZOJ 1025: [SCOI2009]游戏( 背包dp )
显然题目要求长度为n的置换中各个循环长度的lcm有多少种情况. 判断一个数m是否是满足题意的lcm. m = ∏ piai, 当∑piai ≤ n时是满足题意的. 最简单我们令循环长度分别为piai, ...
- [BZOJ 1025] [SCOI2009] 游戏 【DP】
题目链接:BZOJ - 1025 题目分析 显然的是,题目所要求的是所有置换的每个循环节长度最小公倍数的可能的种类数. 一个置换,可以看成是一个有向图,每个点的出度和入度都是1,这样整个图就是由若干个 ...
- bzoj 1025 [SCOI2009]游戏(置换群,DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1025 [题意] 给定n,问1..n在不同的置换下变回原序列需要的不同排数有多少种. [ ...
- [bzoj 1025][SCOI2009]游戏(DP)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1025 分析:首先这个问题等价于A1+A2+……Ak=n,求lcm(A1,A2,……,Ak)的种 ...
- BZOJ 1025 SCOI2009 游戏 动态规划
标题效果:特定n.行定义一个替代品1~n这种更换周期发生后,T次要(T>0)返回到原来的顺序 找到行的所有可能的数 循环置换分解成若干个,然后行位移数是这些周期的长度的最小公倍数 因此,对于一些 ...
- BZOJ 1025: [SCOI2009]游戏 [置换群 DP]
传送门 题意:求$n$个数组成的排列变为升序有多少种不同的步数 步数就是循环长度的$lcm$..... 那么就是求$n$划分成一些数几种不同的$lcm$咯 然后我太弱了这种$DP$都想不出来.... ...
- bzoj 1025: [SCOI2009]游戏【数学+dp】
很容易发现行数就是lcm环长,也就是要求和为n的若干数lcm的个数 有结论若p1^a1+p2^a2+...+pm^am<=n,则ans=p1^a1p2^a2..*pm^am是n的一个可行答案.( ...
- BZOJ 1025 [SCOI2009]游戏 (DP+分解质因子)
题意: 若$a_1+a_2+\cdots+a_h=n$(任意h<=n),求$lcm(a_i)$的种类数 思路: 设$lcm(a_i)=x$, 由唯一分解定理,$x=p_1^{m_1}+p_2^{ ...
- 【BZOJ】1025: [SCOI2009]游戏(置换群+dp+特殊的技巧+lcm)
http://www.lydsy.com/JudgeOnline/problem.php?id=1025 首先根据置换群可得 $$排数=lcm\{A_i, A_i表示循环节长度\}, \sum_{i= ...
随机推荐
- java基础知识梳理
java基础知识梳理 1 基本数据类型
- 十天学会单片机Day1点亮数码管(数码管、外部中断、定时器中断)
1.引脚定义 P3口各引脚第二功能定义 标号 引脚 第二功能 说明 P3.0 10 RXD 串行输入口 P3.1 11 TXD 串行输出口 P3.2 12 INT0(上划线) 外部中断0 P3.3 1 ...
- ok6410的DMA裸机总结
1.为何使用DMA:为了提高CPU的工作效率,避免多余的等待时间 2.关于DMA控制器:(1)通道数:2440有4个通道,6410有4个DMA控制器(初始化的时候要选择),32个通道.210有两种DM ...
- ASP.NET Core文章汇总
现有Asp.Net Core 文章资料,2016 3-20月汇总如下 ASP.NET Core 1.0 与 .NET Core 1.0 基础概述 http://www.cnblogs.com/Irvi ...
- python 面向对象、特殊方法与多范式、对象的属性及与其他语言的差异
1.python 面向对象 文章内容摘自:http://www.cnblogs.com/vamei/archive/2012/06/02/2532018.html 1.__init__() 创建对 ...
- java基本概念
什么是环境变量? 环境变量通常是指在操作系统当中,用来指定操作系统运行时需要的一些参数.通常为一系列的键值对. path环境变量的作用 path环境变量是操作系统外部命令搜索路径 什么是外部命令搜索路 ...
- Ubuntu下编译内核
一.下载源代码和编译软件的准备 下载内核源代码:http://www.kernel.org/ 注意,点击2.6.25内核的F版,即完整版. 如果你懒得去网站点联接,运行下列命令: 代码: $cd ~ ...
- 使用工厂bean和Utility Schema定义集合
工厂bean是实现了beanFactory接口的bean,也可以继承AbstractFactoryBean,主要是用于在给定属性参数之后自动创建一个bean对象. 我们在使用基本集合标记定义集合时,不 ...
- super的用法
1.调用父类的构造方法子类可以调用由父类声明的构造方法.但是必须在子类的构造方法中使用super关键字来调用. 2.操作被隐藏的成员变量和被覆盖的成员方法如果想在子类中操作父类中被隐藏的成员变量和被覆 ...
- poj 2367 Genealogical tree
题目连接 http://poj.org/problem?id=2367 Genealogical tree Description The system of Martians' blood rela ...