您的位置:首页 > 其它

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 之后构造置换,根据贪心的原则,按循环长度从小到大构造答案即可。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: