BZOJ 1025 SCOI2009 游戏 动态规划

题目大意:给定n,定义一个置换的排数为1~n的循环经过这个置换最少T次(T>0)可以回到原来的序列 求所有可能的排数的数量

将一个置换分解为一些循环,那么这个置换的排数就是这些循环的长度的最小公倍数

于是对于一个数,我们验证这个数是否是排数的方式就是将这个数分解质因数,令x=p1^a1*p2^a2*...*pk^ak,若p1^a1+p2^a2+...+pk^ak<=n,则x就是可能的排数

分组背包即可 令f[i][j]表示用前i个质数,和为j能得出的数的数量 每组的物品是pi^1~pi^ai

时间复杂度O(n/lgn*logn*n)=O(n^2)

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 1010
using namespace std;
typedef long long ll;
int n,prime[M],tot;
bool not_prime[M];
ll f[M][M],ans;//f[i][j]表示用前i个质数,和为j能得出的数的数量
void Linear_Shaker()
{
	int i,j;
	for(i=2;i<=n;i++)
	{
		if(!not_prime[i])
			prime[++tot]=i;
		for(j=1;j<=tot&&prime[j]*i<=n;j++)
		{
			not_prime[prime[j]*i]=1;
			if(i%prime[j]==0)
				break;
		}
	}
}
int Quick_Power(int x,int y)
{
	int re=1;
	while(y)
	{
		if(y&1)re*=x;
		x*=x;
		y>>=1;
	}
	return re;
}
int main()
{
	int i,j,k,temp;
	cin>>n;
	Linear_Shaker();
	f[0][0]=1;
	for(i=1;i<=tot;i++)
	{
		for(j=0;j<=n;j++)
			f[i][j]+=f[i-1][j];
		for(j=prime[i];j<=n;j*=prime[i])
			for(k=j;k<=n;k++)
				f[i][k]+=f[i-1][k-j];
	}
	for(i=0;i<=n;i++)
		ans+=f[tot][i];
	cout<<ans<<endl;
	return 0;
}
时间: 2024-10-11 04:58:35

BZOJ 1025 SCOI2009 游戏 动态规划的相关文章

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

显然题目要求长度为n的置换中各个循环长度的lcm有多少种情况. 判断一个数m是否是满足题意的lcm. m = ∏ piai, 当∑piai ≤ n时是满足题意的. 最简单我们令循环长度分别为piai,不足n的话,我们令其他循环长度为1, 补到=n为止. 这样它们的lcm显然是=m的. 然后就是一个背包了...dp(i, j) = dp(i - 1, j) + ∑1≤t≤adp( i - 1, j - pt ) 表示前i个质数, 和为j有多少中方案 #include<bits/stdc++.h>

[BZOJ 1025] [SCOI2009] 游戏 【DP】

题目链接:BZOJ - 1025 题目分析 显然的是,题目所要求的是所有置换的每个循环节长度最小公倍数的可能的种类数. 一个置换,可以看成是一个有向图,每个点的出度和入度都是1,这样整个图就是由若干个环构成,这些环的长度和为 n . 因此,就是要求出和为 n 的正整数的最小公倍数的可能情况. 有一个性质:这些正整数中有合数存在的最小公倍数,都可以用全是质数的情况包含. 所以我们只要求出用质数组成的情况就可以了.我们要求的就是,若干个质数,它们的和小于等于 n,它们的最小公倍数情况. 先筛法求出

bzoj 1025 [SCOI2009]游戏(置换群,DP)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1025 [题意] 给定n,问1..n在不同的置换下变回原序列需要的不同排数有多少种. [思路] 对于一个置换,如果分解后的到的循环长度为 A1,A2,A3… 则答案为lcm(A1,A2…)的不同种数,即有多少个不同的lcm满足: A1+A2+A3+…=n lcm=lcm(A1,A2,A3…) 对于A[1..]的lcm, lcm=a1^max{p1}*a2^max{p2}.. 只考虑ma

BZOJ 1025 [SCOI2009]游戏

之前找LLJ大佬推荐水题的时候让我做这个,然后不出意料的我不会. 日常抄题解. 手玩几组数据发现它N个数可以分成多个组,每个组为一个循环,他们的LCM就是最后的层数. 预处理出n以内的所有质数,我们可以把n分解成p1^a1+p2^a2+p3^a3...不同的p之间的lcm数可以直接相乘,我们用dp递推地算答案,dp[i][j表示前i个质数和为j的lcm数,然后就可以DP了. 最后统计答案要把0~n的dp[p[0]][i]加起来,因为每个数可以单成一组. #include<cstdio> #in

bzoj 1025 [SCOI2009]游戏 dp

题面 题目传送门 解法 显然,可以回到初始状态就意味着一定由若干个环组成 假设环的长度为\(l_i\) 那么,我们可以得到\(\sum l_i=n\) 不考虑自环的情况,那么\(\sum l_i≤n\) 将\(n\)以内的质因数全部筛出,强制每一次只取某一个质数的次幂,那么就可以解决重复计数的问题 时间复杂度:\(O(n^2)\) 代码 #include <bits/stdc++.h> #define int long long #define N 1010 using namespace s

【BZOJ 1025】 [SCOI2009]游戏

1025: [SCOI2009]游戏 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 1273  Solved: 805 [Submit][Status] Description windy学会了一种游戏.对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应.最开始windy把数字按顺序1,2,3,--,N写一排在纸上.然后再在这一排下面写上它们对应的数字.然后又在新的一排下面写上它们对应的数字.如此反复,直到序列再次变为1,2,3,--,N

BZOJ1025: [SCOI2009]游戏

1025: [SCOI2009]游戏 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2029  Solved: 1315[Submit][Status][Discuss] Description windy学会了一种游戏.对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应.最开始windy把数字按顺序1,2,3,……,N写一排在纸上.然后再在这一排下面写上它们对应的数字.然后又在新的一排下面写上它们对应的数字.如此反复,直到序列再次变为1,

SCOI2009游戏

1025: [SCOI2009]游戏 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1065  Solved: 673[Submit][Status] Description windy学会了一种游戏.对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应.最开始windy把数字按顺序1,2,3,……,N写一排在纸上.然后再在这一排下面写上它们对应的数字.然后又在新的一排下面写上它们对应的数字.如此反复,直到序列再次变为1,2,3,……,N.

矩阵乘法专题1——bzoj 1297 [SCOI2009] 迷路题解

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B