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;
    }

     

  • 相关阅读:
    Struts2+Spring3+Mybatis3开发环境搭建
    spring+struts2+mybatis
    【LeetCode】Populating Next Right Pointers in Each Node
    【LeetCode】Remove Duplicates from Sorted Array
    【LeetCode】Remove Duplicates from Sorted Array II
    【LeetCode】Binary Tree Inorder Traversal
    【LeetCode】Merge Two Sorted Lists
    【LeetCode】Reverse Integer
    【LeetCode】Same Tree
    【LeetCode】Maximum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2844889.html
Copyright © 2011-2022 走看看