zoukankan      html  css  js  c++  java
  • poj 3590 The shuffle Problem 置换群+DP

      我们根据置换群的性质,知道其经过 K 次置换回到最初位置,

    此时 K,为N元组的循环因子 a1,a2,...,ai 的最小公倍数。

      现在题目要求输入N,求出最大的K,当K情况不唯一,则输出字典序最小,

    那么题目就转换成将 N 分解成 X个数,其最小公倍数最大的情况了。

      这里关于分解N的处理,也是参考一神牛,(再次ORZ一下)

      因为 N <= 100 ,我们可以使用 DP 来得到。

      F[ i ][ j ] = Max {  F[ i ][ j ] , LCM( F[ i-k ][ j ], k )  }

      定义 F[ i ][ j ] 表示 和为 i 分解为 j 个数时 的最小公倍数最大的值

      通过保留最值及路径,来得出结果,ORZ神牛犀利的处理方案

      具体看代码

    解题代码

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<algorithm>
    using namespace std;
    
    const int N = 110;
    
    int f[N][N], d[N][N];
    int val[N], size;
    
    int gcd(int a,int  b)
    {    return (b==0)? a : gcd(b,a%b); }
    int lcm(int a,int b)
    {    return a/gcd(a,b)*b; }
    
    void init()
    {
        memset( f, 0, sizeof(f));
        for(int i = 0; i < N; i++)
        {
            f[i][0] = 1;
            f[i][1] = i; 
        }
        // f[i][j]: 和为i,分解成j个数的最小公倍数 最大值    
        for(int i = 2; i <= 100; i++)
        {
            for(int j = 2; j <= i; j++)
            {
                for(int k = 1; k <= i-j+1; k++) //分解为j个数时,k最大为 i-j+1 , 其余j-1个1 
                {
                    int tmp = lcm( f[i-k][j-1], k );
                    if( tmp > f[i][j] )
                    {
                        f[i][j] = tmp; d[i][j] = i-k; //保存k, 则当前因子为i-k,记忆路径    
                    }
                }
                if( f[i][j] >= f[i][ f[i][0] ] ) //取等号,最大值相同时,J越大,字典序越小
                    f[i][0] = j; //存储i时最大值的位置
            }
        }
    }
    void dfs( int i, int j )
    {
        if( j == 1 ){ val[size=0] = i; return; }
        dfs( d[i][j], j-1 );
        val[ ++size ] = i-d[i][j];
    }
    int main()
    {
        init();
    
        int T, n;
        scanf("%d", &T);
        while( T-- )
        {
            scanf("%d", &n);
            printf("%d", f[n][ f[n][0] ] );
        
            dfs( n, f[n][0] ); //通过递归得到 n分解为j个数,存储到数组val[]中
            size++;
    
            sort( val, val+size );
        
            int s = 0;
            for(int i = 0; i < size; i++)
            {
                int num = val[i];
                for(int j = s+2; j <= s+val[i]; j++)
                    printf(" %d", j);
                printf(" %d",s+1);
                s = s+val[i];
            }
            puts("");    
        }
        return 0;
    }

     

  • 相关阅读:
    monaco editor
    javascript for of 和 for in 在数组和对象中的区别
    django rest 版本控制器
    学习
    day 22
    day 21
    day20
    day21 数据处理自我小结
    day20 【手写数字识别】之数据处理(搬运)
    day19 通过极简方案快速构建手写数字识别模型 (百度飞浆搬运)
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2844889.html
Copyright © 2011-2022 走看看