HDU 5916 Harmonic Value Description

题目来源:2016 CCPC 长春站
题意:
定义一个排列p1,p2,p3....pn的调和数值如下方公式。例如一个数列 1,2,3,4,5 的调和值就为4。
现在给出一个k,求出调和值第k小的一个permutation,这个permutation不唯一
调和数值计算公式

思路:
首先可以先构造出来一个调和值为k的一对数,然后再让其他数前后调和值为1就ok了。
如果两个数gcd() = k , num1 = i * k , num2 = j * k ( i != j && i , j >= 1 ),那最小的两个数就为 k 和 2k 正好与题目中数据范围提示相对应

For each test case, there is only one line describing the given integers n and k (1≤2k≤n≤10000).

  1. 说明现在的思路是正确的,接下来的问题很重要,如何保证后面的排列中相邻两个数的gcd = 1呢?
    只需要让序列为2k,k,k-1,k-2....1,k+1,k+2....2k-1, 2k+1,.....n即可,或者是2k,k,k-1,k-2....1,n,n-1...,2k+1,2k-1,.....,k+1

  2. 那能不能交换一下2k和k的位置?
    不能,如果交换位置后序列为了保持后面排列中相邻两个数gcd = 1就得这样排序k,2k,2k-1,2k-2....k+1,k-1,...1,2k+1,2k+2....n,需要注意的是 k+1 和 k-1的gcd 不一定等于1例如k = 3 gcd(2,4) = 2

     /*************************************************************************
       > File Name: test3.cpp
         > Author:    WArobot 
         > Blog:      http://www.cnblogs.com/WArobot/ 
         > Created Time: 2017年04月17日 星期一 14时03分28秒
      ************************************************************************/
    
     #include<bits/stdc++.h>
     using namespace std;
    
     int n,k;
     void solve(){
     	printf(" %d %d",2*k,k);
     	for(int i=k-1;i;i--)	printf(" %d",i);
     	for(int i=n;i>=k+1;i--){
     		if(i!=2*k)	printf(" %d",i);
     	}
     	printf("\n");
     }
     int main(){
     	int t , kase = 0;
     	scanf("%d",&t);
     	while(t--){
     		scanf("%d%d",&n,&k);
     		printf("Case #%d:",++kase);
     		solve();
     	}
     	return 0;
     }
    

刚开始不清楚permutation是不是唯一的,按逻辑来讲自然是不唯一,但是真正去做的时候却不敢去尝试了,总想一次性做对,太过理想化了。

posted @ 2017-04-17 16:03  ojnQ  阅读(87)  评论(0编辑  收藏  举报