poj 3590
2015-08-20 20:52
387 查看
题目大意:
设 kk 为满足 Pk=eP^k = e 的最小的非负整数 。
构造出长度为 nn 的置换 PP,使得 kk 最大,
若有多个置换 kk 值相同,输出字典序最小的。
记 pip_i 为 PP 的循环长度。那么 k=lcm(p1,p2,p3...pt)k = lcm(p_1,p_2,p_3 ... p_t)
1.考虑 p1p_1,p2p_2,lcm(p1,p2)=p1∗p2gcd(p1,p2)lcm(p_1,p_2) = \frac {p_1*p_2} {gcd(p_1,p_2)}。
根据贪心,gcd(p1,p2)=1gcd(p_1,p_2) = 1 时是最优的,此时 k=∏ti=1pik = \prod_{i=1}^t p_i
2.考虑 p1≠1p_1 \neq 1, p2≠1p_2 \neq 1 且 gcd(p1,p2)=1 gcd(p_1,p_2) = 1,
如果把 p1p_1,p2p_2 合并成一个置换,长度为 p1+p2p_1 + p_2,
那么它对答案贡献为 p1+p2<p1∗p2p_1 + p_2< p_1*p_2,
所以长度不为 11 的置换合并之后反而不是更优的。
综上所述,pip_i 为质数的幂或者 11 是最优的。
求出 pip_i 之后构造置换,根据贪心的原则,按循环长度从小到大构造答案即可。
设 kk 为满足 Pk=eP^k = e 的最小的非负整数 。
构造出长度为 nn 的置换 PP,使得 kk 最大,
若有多个置换 kk 值相同,输出字典序最小的。
记 pip_i 为 PP 的循环长度。那么 k=lcm(p1,p2,p3...pt)k = lcm(p_1,p_2,p_3 ... p_t)
1.考虑 p1p_1,p2p_2,lcm(p1,p2)=p1∗p2gcd(p1,p2)lcm(p_1,p_2) = \frac {p_1*p_2} {gcd(p_1,p_2)}。
根据贪心,gcd(p1,p2)=1gcd(p_1,p_2) = 1 时是最优的,此时 k=∏ti=1pik = \prod_{i=1}^t p_i
2.考虑 p1≠1p_1 \neq 1, p2≠1p_2 \neq 1 且 gcd(p1,p2)=1 gcd(p_1,p_2) = 1,
如果把 p1p_1,p2p_2 合并成一个置换,长度为 p1+p2p_1 + p_2,
那么它对答案贡献为 p1+p2<p1∗p2p_1 + p_2< p_1*p_2,
所以长度不为 11 的置换合并之后反而不是更优的。
综上所述,pip_i 为质数的幂或者 11 是最优的。
求出 pip_i 之后构造置换,根据贪心的原则,按循环长度从小到大构造答案即可。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <string> #include <vector> #include <stack> #include <queue> #include <utility> #include <iostream> #include <algorithm> template<class Num>void read(Num &x) { char c; int flag = 1; while((c = getchar()) < '0' || c > '9') if(c == '-') flag *= -1; x = c - '0'; while((c = getchar()) >= '0' && c <= '9') x = (x<<3) + (x<<1) + (c-'0'); x *= flag; return; } template<class Num>void write(Num x) { if(x < 0) putchar('-'), x = -x; static char s[20];int sl = 0; while(x) s[sl++] = x%10 + '0',x /= 10; if(!sl) {putchar('0');return;} while(sl) putchar(s[--sl]); } #define REP(__i,__start,__end) for(int __i = (__start); __i <= (__end); __i++) const int tot = 25, size = 30; int prime[size] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}; long long maxlcm; int n, c[size], p[size]; void dfs(int s,int rem,long long lcm) { if(s == tot + 1) { if(lcm > maxlcm) { maxlcm = lcm; REP(i, 1, tot) c[i] = p[i]; } return; } int calc = prime[s]; p[s] = 0, dfs(s + 1, rem, lcm); while(calc <= rem) { p[s] = calc; dfs(s + 1, rem - calc, lcm * calc); calc *= prime[s]; } } void output() { int pl = 0, rm = n, pos; write(maxlcm), putchar(' '); REP(i, 1, tot) if(c[i]) { p[++pl] = c[i]; rm -= c[i]; } REP(i, 1, rm) write(i), putchar(' '); pos = rm; std::sort(p + 1, p + pl + 1); REP(i, 1, pl) { REP(j, 2, p[i]) { write(pos + j); putchar(' '); } write(pos + 1); putchar(' '); pos += p[i]; } puts(""); } int main() { int T; #ifndef ONLINE_JUDGE freopen("3590.in","r",stdin); freopen("3590.out","w",stdout); #endif read(T); while(T--) { memset(c, 0, sizeof(c)); read(n); maxlcm = 0, dfs(1, n, 1); output(); } #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); #endif return 0; }
相关文章推荐
- 程序员的生活充满压力,但你不能放弃!
- HDU 1465 不容易系列之排错
- 最少转弯问题
- 明远imx6
- 第六篇 SQL Server安全执行上下文和代码签名
- Cocos2d-x 之 八方向小摇杆
- 【ZJOI2013】K 大数查询 ( 树状数组套线段树 )
- css基础精华05
- HDU 5414 CRB and String
- Centos7下Amarok播放mp3
- curl 要么 file_get_contents 获得授权页面的方法的必要性
- hive与hbase集成
- Heartbeat概念详解
- 如何隐藏导航栏下的线
- css基础精华04
- Java值传递以及引用的传递、数组的传递!!
- android 添加视频、图片、录音上传(一)
- Html标签
- Phantomjs 根据Casperjs源码拓展download方法
- 数组的异常及处理