UVA, 11129 An antiarithmetic permutation

题意:读入一个数n,代表从0到n-1的数列,让你输出一个数列,这个数列的子序列均不为等差数列

思路:= =参考了网上大神的代码,得到的一个规律:将等差(?)数列按奇偶位置分成两个数列,再重复这一步骤,最后得到的数列一定是非等差数列,其实就是分治法

  ps:分治法:将大的问题分为无数个小问题,解决后再将得到的解合并,得到大问题的答案

例:0 1 2 3 4 5 6 7

 ->(0 2 4 8)(1 3 5 7) 此刻我们得到了两个小等差数列,但此时数列已不是等差数列了

 ->(0 4)(2 8)(1 5)(3 7)= =因为数列个数小于3,因而小数列已无法判断是否等差,但此刻数列已满足要求,即子序列不为等差数列

下面是代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 int num;
 5 int n[10000],t[10000];
 6 bool datecin()
 7 {
 8     if(scanf("%d",&num)!=EOF&&num)
 9         return true;
10     return false;
11 }
12
13 void dateins()
14 {
15     for(int i=0;i<num;i++)n[i]=i;
16 }
17
18 void datecal(int l,int r)
19 {
20     if(r-l<2) return ;
21     for(int i=l;i<=r;i++)t[i]=n[i];
22     int c=l;
23     for(int i=l;i<=r;i+=2)  n[c++]=t[i];
24     for(int i=l+1; i<=r; i+=2) n[c++]=t[i];//排序数列里的值
25     datecal(l,(l+r)/2);//对左子序列排序
26     datecal((l+r)/2+1,r);//对右子序列排序
27 }
28
29 void showres()
30 {
31     printf("%d:",num);
32     for(int i=0;i<num;i++)
33     {
34         printf("%d",n[i]);
35         if(i!=num-1)
36             printf(" ");
37     }
38     printf("\n");
39 }
40
41 int main()
42 {
43     while(datecin())
44     {
45         dateins();
46         datecal(0,num-1);
47         showres();
48     }
49     return 0;
50 }

答案有多种,应该是有其他的方法,后面再找一找。

时间: 2024-09-29 21:12:50

UVA, 11129 An antiarithmetic permutation的相关文章

uva:11129 - An antiarithmetic permutation(分治法)

题目:11129 - An antiarithmetic permutation 题目大意:求n的反算术级数.就是排序0 ..n - 1 要求不存在长度大于2的序列.例如:5的序列排列后(0, 5, 4, 3, 1, 2) ,但是(0,1,2)是一个等差序列,同样的还有(5,4,3), (5,3,1)... 解题思路:这题需要找到排列的策略:将整个序列分成差不多等长的两个部分,使得左右两部分各自成为等差数列,这样左边的数和右边的数组合就一定不会出现等差数列.然后把这个作为子问题,递归求解.递归到

uva 11129 An antiarithmetic permutation (递归)

uva 11129 An antiarithmetic permutation A permutation of n+1 is a bijective function of the initial n+1 natural numbers: 0, 1, ... n. A permutation p is called antiarithmetic if there is no subsequence of it forming an arithmetic progression of lengt

uva--11129An antiarithmetic permutation+分治

题意: 输入一个数n,求n的一个排列,要求这个排序的任意一个子序列都不能是等差数列. 思路: 想了很久,但是除了枚举以外还是没想到其它的思路,枚举是一定会超时的;到网上看了别人的解题报告 才知道应该用分治的方法做. 分治的思想:考虑一个等差数列,我们把其奇数项,偶数项都提取出来;显然这两个序类内部还是等差数列,但是 它们之间的元素就不可能形成等差数列了;然后我们可以对得到的两个序列再进行同样的划分.....这样多次划分以后就可以保证整个序列没有子序列为等差数列了. 代码如下: #include<

Uva 11077 Find the Permutation

可以发现最优的方案就是一个循环节内互换. 所以一个有n个元素,c个循环节的置换的交换次数(最少)是n-c. 然后就可以递推了,把i插入到前i-1个元素构成的置换中,要么新成立一个循环,要么加入到之前的任意循环中去. 所以f[i][j]=f[i-1][j]+f[i-1][j-1]*(i-1) #include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<alg

UVA题目分类

题目 Volume 0. Getting Started 开始10055 - Hashmat the Brave Warrior 10071 - Back to High School Physics 10300 - Ecological Premium 458 - The Decoder 494 - Kindergarten Counting Game 414 - Machined Surfaces 490 - Rotating Sentences 445 - Marvelous Mazes

uva 1485 - Permutation Counting(递推)

题目链接:uva 1485 - Permutation Counting 题目大意:给定n和k,要求求一个由1~n组成的序列,要求满足ai>i的i刚好有k个的序列种数. 解题思路:dp[j][i]表示长度为i,j个位置满足的情况. dp[j+1][i]+=dp[j][i]?(j+1); 1, (3), (4), 2: 括号位置代表ai>i,既满足位置,此时i = 4, j = 2. -> 1, (3), (4), 2, 5 1 种,在最后追加 -> 1, (5), (4), 2,

uva 11922 - Permutation Transformer(伸展树)

题目链接:uva 11922 - Permutation Transformer 题目大意:给定一个序列,每次操作取出区间a~b,翻转后放到末尾,随后输出序列. 解题思路:就是伸展树,对于每个节点设一个flip,表示是否为翻转转态.每次将a旋转到根,然后分裂,再将b翻转到根,分裂,然后将mid翻转放到最后. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; str

UVA 11525 Permutation(树状数组)

题目意思是说  给你一个数k  然后有k个si   问你1--k 的第n个全排列是多少   注意是 1 2 3...k的全排列 不是si的 N=   由观察得知(k-i)!就是k-i个数字的全排列种数, 0=<Si<=k-i,所以显然可知假设当i==1时从第(k-1)!*s1到第n个全排列都是由第S1+1个数字开始的数列,因为每(k-1)!次排列过后,下一个排列的第1个数字都要增大1(每隔(k-1)!次,这k-1个数字都排列过一遍了,下一次只能增大更前面一个,也就是第1个了) 比如对于数列{1

UVA - 11525 Permutation

题意:求1-k的排列中第n大的序列,题目给出n的计算方法: n = si*(k-1)+s2*(k-2)...+sk*0!; 并给你s1-sk 思路:首先我们明确,比如321是集合{1,2,3}的第几大的序列,从第一位开始3开头的话,那么显然这个序列的前面就一定会有1,2开头的学列,就是2*2!,依次类推我们就可以确定这个学列是第几大的了,但是要注意到用过的数将不再被我们考虑在内,现在这道题目是反过来了,可以琢磨一下si的含义是剩下没用的数中第(si+1)大的数,我们通过线段树来处理,0,1,分别