博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ 1025] [SCOI2009] 游戏 【DP】
阅读量:5094 次
发布时间:2019-06-13

本文共 1340 字,大约阅读时间需要 4 分钟。

题目链接:

 

题目分析

显然的是,题目所要求的是所有置换的每个循环节长度最小公倍数的可能的种类数。

一个置换,可以看成是一个有向图,每个点的出度和入度都是1,这样整个图就是由若干个环构成,这些环的长度和为 n 。

因此,就是要求出和为 n 的正整数的最小公倍数的可能情况。

有一个性质:这些正整数中有合数存在的最小公倍数,都可以用全是质数的情况包含。

所以我们只要求出用质数组成的情况就可以了。我们要求的就是,若干个质数,它们的和小于等于 n,它们的最小公倍数情况。

先筛法求出 n 以内的所有素数。然后使用 DP:

f[i][j] 表示前 i 个素数之内,组成的和为 j ,LCM 的种类数。

f[i][j] = f[i - 1][j] + sigma(f[j - Prime[i]^k])

初始状态是 f[0][0] = 1

当一些质数的和不同的时候,它们的积一定不同。

 

代码

#include 
#include
#include
#include
#include
#include
using namespace std;const int MaxN = 1000 + 5;int n, Top;int Prime[MaxN];bool isPrime[MaxN];typedef long long LL;LL Ans;LL f[MaxN][MaxN];int main(){ scanf("%d", &n); for (int i = 1; i <= n; ++i) isPrime[i] = true; isPrime[1] = false; Top = 0; for (int i = 2; i <= n; ++i) { if (isPrime[i]) Prime[++Top] = i; for (int j = 1; j <= Top && i * Prime[j] <= n; ++j) { isPrime[i * Prime[j]] = false; if (i % Prime[j] == 0) break; } } f[0][0] = 1; for (int i = 1; i <= Top; ++i) { for (int j = 0; j <= n; ++j) f[i][j] = f[i - 1][j]; for (int j = 0; j <= n; ++j) for (int k = Prime[i]; k <= n - j; k *= Prime[i]) f[i][j + k] += f[i - 1][j]; } Ans = 0; for (int i = 0; i <= n; ++i) Ans += f[Top][i]; printf("%lld\n", Ans); return 0;}

  

转载于:https://www.cnblogs.com/JoeFan/p/4319996.html

你可能感兴趣的文章
App右上角数字
查看>>
小算法
查看>>
201521123024 《java程序设计》 第12周学习总结
查看>>
新作《ASP.NET MVC 5框架揭秘》正式出版
查看>>
IdentityServer4-用EF配置Client(一)
查看>>
WPF中实现多选ComboBox控件
查看>>
读构建之法第四章第十七章有感
查看>>
Windows Phone开发(4):框架和页 转:http://blog.csdn.net/tcjiaan/article/details/7263146
查看>>
python asyncio 异步实现mongodb数据转xls文件
查看>>
TestNG入门
查看>>
【ul开发攻略】HTML5/CSS3菜单代码 阴影+发光+圆角
查看>>
IOS-图片操作集合
查看>>
IO—》Properties类&序列化流与反序列化流
查看>>
测试计划
查看>>
Mysql与Oracle 的对比
查看>>
jquery实现限制textarea输入字数
查看>>
Codeforces 719B Anatoly and Cockroaches
查看>>
c# 泛型+反射
查看>>
第九章 前后查找
查看>>
Python学习资料
查看>>