1025: [SCOI2009]游戏

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit:
1065  Solved: 673
[Submit][Status]

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

【数据规模和约定】
30%的数据,满足
1 <= N <= 10 。
100%的数据,满足 1 <= N <= 1000 。

HINT

题解:

题目所描述的对应变换关系实质就是一个置换
而任意一个置换都可以写成若干轮换的乘积。如题目所述1->2  2->3  3->1  4->5  5->4  6->6,可以写成:
(1 2 3)(4 5)(6) 
排数实际上就是若干循环节长度的最小公倍数。这里就是:3*2*1
因此所求即是:加和恰好为N的若干正整数的最小公倍数的可能数。
首先,由于1不影响最小公倍数(若干个整数里面就有可能有1),所以,问题转化为:
加和小于等于N的若干正整数的最小公倍数的可能数。
对于a1+a2+a3+a4+...+ai<=N里,任意一个正整数ai都可以表示为若干个素数的乘积  ps:我想到这儿就不会了……
对于这若干个素数:乘积>=和
所以问题就转化为:加和小于等于N的若干只含一个质因数的正整数的最小公倍数的可能数。
然后先弄一个素数表。
用dp[i,j]表示前i个素数(和它的k次幂)之和小于等于j时有多少个最小公倍数
则答案为dp[num,n](num为小于等于N的素数个数)
方程为
dp[i,j]:=sum(dp[i-1,j-sushu[i]^k])注意k>=0且sushu[i]^k<=j
这个公式不完全对,当k=0的时候要特殊处理!这个时候加的值不是dp[i-1,j-1]而是dp[i-1,j]。

实际上,问题到了后面,也就是到了将问题转化为加和小于等于N的若干只含一个质因数的正整数的最小公倍数的可能数。

这俨然已经成为了一个背包问题求构成种数的问题。

有一个容量为n个背包,有很多物体,它们的体积分别问:

1,2,2*2,2*2*2,……3,3*3,3*3*3……

并且是01背包问题(除了1可以无限用),你想放两个2*2,和放一个2*2再放4个1的最小公倍数不是一样的吗?枚举到一个上限即可

下面我将给出三份代码:

一、vijosp1071新年趣事之打牌(这是我第一次接触背包问题求构成种数的问题,所以文件里有记录)

题目附在另一篇文章里

代码如下:

 var n,i,j,tot,ans:longint;
a,f,g:array[..] of longint;
p:array[..]of boolean;
begin
readln(tot);
readln(n);f[]:=;
for i:= to n do readln(a[i]);
for i:= to n do
for j:=tot downto a[i] do
begin
if (f[j-a[i]]>) and (f[j]=) then g[j]:=i;
f[j]:=f[j]+f[j-a[i]];
end;
i:=tot;
if f[tot]> then begin writeln('-1');halt;end;
if f[tot]= then begin writeln('');halt;end;
while (i>) and (g[i]<>) do
begin
p[g[i]]:=true;
i:=i-a[g[i]];
end;
for i:= to n do if not p[i] then write(i,' ');
end.

二、本题二维做法,比较费空间

代码:

 var i,j,k,n,tot,tmp:longint;
check:array[..] of boolean;
p:array[..] of longint;
f:array[..,..] of int64;
procedure getprimes;
var i,j,k:longint;
begin
tot:=;
fillchar(check,sizeof(check),true);
for i:= to n do
begin
if check[i] then begin inc(tot);p[tot]:=i;end;
for j:= to tot do
begin
k:=i*p[j];
if k>n then break;
check[k]:=false;
if i mod p[j]= then break;
end;
end;
end;
procedure main;
begin
readln(n);
getprimes;
for i:= to n do f[,i]:=;
for i:= to tot do f[i,]:=;
for i:= to tot do
begin
for j:= to n do
begin
inc(f[i,j],f[i-,j]);
k:=p[i];
while k<=j do
begin
inc(f[i,j],f[i-,j-k]);
k:=k*p[i];
end;
end;
end;
writeln(f[tot,n]);
end;
begin
main;
end.

三、本题一维做法

代码:

 var i,j,k,n,tot,tmp:longint;
check:array[..] of boolean;
p:array[..] of longint;
f:array[..] of int64;
procedure getprimes;
var i,j,k:longint;
begin
tot:=;
fillchar(check,sizeof(check),true);
for i:= to n do
begin
if check[i] then begin inc(tot);p[tot]:=i;end;
for j:= to tot do
begin
k:=i*p[j];
if k>n then break;
check[k]:=false;
if i mod p[j]= then break;
end;
end;
end;
procedure main;
begin
readln(n);
getprimes;
for i:= to n do f[i]:=;
for i:= to tot do
for j:=n downto do
begin
k:=p[i];
while k<=j do
begin
inc(f[j],f[j-k]);
k:=k*p[i];
end;
end;
writeln(f[n]);
end;
begin
main;
end.

需要注意一点:将二维转化为一维后,内循环变成了倒序,而二维的话是不用考虑这个的(自己想想为什么)

SCOI2009游戏的更多相关文章

  1. BZOJ 1025 [SCOI2009]游戏

    1025: [SCOI2009]游戏 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1533  Solved: 964[Submit][Status][ ...

  2. BZOJ 1025: [SCOI2009]游戏( 背包dp )

    显然题目要求长度为n的置换中各个循环长度的lcm有多少种情况. 判断一个数m是否是满足题意的lcm. m = ∏ piai, 当∑piai ≤ n时是满足题意的. 最简单我们令循环长度分别为piai, ...

  3. 【BZOJ1025】[SCOI2009]游戏(动态规划)

    [BZOJ1025][SCOI2009]游戏(动态规划) 题面 BZOJ 洛谷 题解 显然就是一个个的置换,那么所谓的行数就是所有循环的大小的\(lcm+1\). 问题等价于把\(n\)拆分成若干个数 ...

  4. bzoj千题计划116:bzoj1025: [SCOI2009]游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1025 题目转化: 将n分为任意段,设每段的长度分别为x1,x2,…… 求lcm(xi)的个数 有一个 ...

  5. AC日记——[SCOI2009]游戏 bzoj 1025

    [SCOI2009]游戏 思路: 和为n的几个数最小公倍数有多少种. dp即可: 代码: #include <bits/stdc++.h> using namespace std; #de ...

  6. 【bzoj1025】[SCOI2009]游戏

    1025: [SCOI2009]游戏 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1987  Solved: 1289[Submit][Status] ...

  7. BZOJ_1025_[SCOI2009]游戏_DP+置换+数学

    BZOJ_1025_[SCOI2009]游戏_DP+置换 Description windy学会了一种游戏.对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应.最开始windy把数字按 顺序1 ...

  8. BZOJ1025: [SCOI2009]游戏

    Description windy学会了一种游戏.对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应.最开始windy把数字按顺序1,2,3,……,N写一排在纸上.然后再在这一排下面写上它们对 ...

  9. 1025: [SCOI2009]游戏 - BZOJ

    Description windy学会了一种游戏.对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应.最开始windy把数字按顺序1,2,3,……,N写一排在纸上.然后再在这一排下面写上它们对 ...

随机推荐

  1. php入门变量

    变量是用于临时存储值的容器.这些值可以是数字.文本,或者是复杂得多的数据. PHP 具有8种变量. 其中包括4种标量(单值)类型——字符串型(字符).整型.浮点型(小数)和布尔型(TRUE或FALSE ...

  2. Kakfa揭秘 Day5 SocketServer下的NIO

    Kakfa揭秘 Day5 SocketServer下的NIO 整个Kafka底层都是基于NIO来进行开发的,这种消息机制可以达到弱耦合的效果,同时在磁盘有很多数据时,会非常的高效,在gc方面有非常大的 ...

  3. Opencv 的数据结构

    opencv的基本数据结构 结构 成员 意义 CvPoint int x,y 图像中的点 CvPoint2D32f float x,y 二维空间中的点 CvPoint3D32f float x,y,z ...

  4. unity3d应用内分享(微信、微博等)的实现

    问题:如何在unity3d的游戏中实现分享功能,如图 思路: 1.分享功能的实现方式有多种,较方便快捷的一种是直接调用android的API来调出系统的分享界面 2.unity3d里面调用androi ...

  5. windows 2008 R2 Activition

    无需破解:Windows Server 2008 R2 至少免费使用 900天 1.首先安装后,有一个180天的试用期. 2.在180天试用期即将结束时,使用下面的评估序列号激活Svr 2008 R2 ...

  6. SwfUpload vs里运行可以上传文件,放到iis上上传就报404错误。

    网上的答案都是说swfupload 的upload_url 路径要设置成绝对路径,但是我也设置了,但是还是不行,然后又找了方法,终于找到了,点击这里查看 解决办法: <system.webSer ...

  7. 在SpringMVC利用MockMvc进行单元测试

    spring在线文档:https://docs.spring.io/spring/docs/current/javadoc-api/index.html?index-files/index-13.ht ...

  8. 用JavaScript获取页面上被选中的文字的技巧

    这里介绍的一个小技巧是如何用JavaScript获取页面上被选中的文字的方法.最关键的JavaScript API是: event.selection = window.getSelection(); ...

  9. Educational Codeforces Round 11

    A. Co-prime Array http://codeforces.com/contest/660/problem/A 题意:给出一段序列,插进一些数,使新的数列两两成互质数,求插最少的个数,并输 ...

  10. hdu 1018

    数学题  用的这个方法比较烂 g++超时  c++ 406ms /******************************************************************* ...