zoukankan      html  css  js  c++  java
  • 数论+DP HDOJ 4345 Permutation

    题目传送门

    题意:一个置换群,经过最少k次置换后还原。问给一个N个元素,在所有的置换群里,有多少个不同的k。

    分析:这道题可以转化成:N = Σ ai ,求LCM ( ai )有多少个不同的值。比如N=10时,k可为:1,2,3,2*2,5,2*3,7,2*2*2,3*3,2*5,2*2*3,2*7,3*5,2*2*5,3*7,2*3*5,共16个,这里用到了唯一分解定理:每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。例如:  。那么先预处理出1000内的素数,dp[i][j]表示用到了前i个素数,组成和为j,的个数,一个素数可能用到多次。因为1对结果不影响,所以结果是Σ dp[m][i] (m最大的素数<=n,i<=n)

    收获:1. 置换群和唯一分解定理 2. DP和数论结合

    代码:

    /************************************************
    * Author        :Running_Time
    * Created Time  :2015-8-27 18:11:40
    * File Name     :F.cpp
     ************************************************/
    
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <bitset>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    typedef long long ll;
    const int N = 1e3 + 10;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e9 + 7;
    int prime[N/2];
    bool is_prime[N];
    ll dp[200][N];
    
    int seive(void)	{
    	int p = 0;
    	memset (is_prime, true, sizeof (is_prime));
    	for (int i=2; i<=1000; ++i)	{
    		if (is_prime[i])	prime[++p] = i;
    		for (int j=1; j<=p && prime[j]*i<=1000; ++j)	{
    			is_prime[i*prime[j]] = false;
    			if (i % prime[j] == 0)	break;
    		}
    	}
    	return p;
    }
    
    int main(void)    {
    	int p = seive ();
    	int n, m = 0;
    	while (scanf ("%d", &n) == 1)	{
    		memset (dp, 0, sizeof (dp));
    		dp[0][0] = 1;
    		for (int i=1; i<=p; ++i)	{
    			for (int j=0; j<=n; ++j)	dp[i][j] = dp[i-1][j];
    			int res = prime[i];
    			if (res <= n)	m = i;
    			else	break;
    			while (res <= n)	{
    				for (int j=0; j+res<=n; ++j)	{
    					if (dp[i-1][j])	dp[i][j+res] += dp[i-1][j];
    				}
    				res *= prime[i];
    			}
    		}
    		ll ans = 0;
    		for (int i=1; i<=n; ++i)	ans += dp[m][i];
    		printf ("%I64d
    ", ans + 1);
    	}
    
        return 0;
    }
    

      

    编译人生,运行世界!
  • 相关阅读:
    mysql运行报The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone的解决方法
    【SpringBoot】服务器端主动推送SSE技术讲解
    【SpringBoot】SpringBoot2.0响应式编程
    【SpringBoot】息队列介绍和SpringBoot2.x整合RockketMQ、ActiveMQ
    第二部分初始阶段 第四章 初始不是需求阶段
    第一部分绪论 第三章 案例研究
    第一部分绪论 第二章 迭代,进化和敏捷
    第一部分绪论 第一章
    java集合(4)-Set集合
    java集合(3)-Java8新增的Stream操作集合
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4765685.html
Copyright © 2011-2022 走看看