9.26T5 CQBZ
2 排序 (sorting.cpp/c/pas)
2.1 问题描述
shell排序是众多排序算法中的一种。给定N个互不相同的整数,存放在数组A中,排成升序。Shell排序的 代码段在附加的shell.cpp中。 此处的i, N, X, gap, temp, ok 均是整数。数组A的元素互不相同,取值范围在1 N之间。如果第11行被遗漏 了,这个有bug的shell排序程序在X取某些值时,仍然有可能得到正确的排序结果。 请你找出所有能得到正确排序结果的X。
1 gap = X; 2 do 3 { ok=1; 4 for (i = 1; i<= N-gap; i++) 5 if (A[i] > A[i+gap]) 6 { temp = A[i]; 7 A[i] = A[i+gap]; 8 A[i+gap] = temp; 9 ok = 0; 10 } 11 if (gap/2 > 1) gap=gap/2; else gap=1; 12 }while (ok == 0);
2.2 输入格式
从sorting.in读取输入文件。
第1行:1个整数N,表示要排序的元素个数
第2行:N个整数,表示要排序的数组A
2.3输出格式
向sorting.out输出你的答案。
第1行:1个整数C,表示X有多少种不同的取值方案,能得到正确排序结果
第2行:C个整数,表示能得到正确排序结果的X的取值
2.4 样例输入
6
4 2 6 1 5 3
2.5 样例输出
2
1 3
2.6 样例解释
有6个元素,分别是4, 2, 6, 1, 5, 3。
能得到正确的排序结果的X有2种取值方案: ∙ X = 1, 我们交换以下这些位置的元素
(1,2), (3,4), (4,5), (5,6), (2,3), (4,5), (1,2), (3,4); ∙
X = 3, 我们交换以下这些位置的元素
(1,4), (3,6).
2.7 数据范围和约定
对于20%的数据,𝑛 ≤ 1000
对于100%的数据,𝑛 ≤ 500000
其实也是一道水题
因为gap不再改变,所以间隔值是固定的,这就导致只会间隔为gap-1的数之间交换
首先构造一个同样的b数组,排完序之后记录一下与原来的位置差,证明这个数在gap-1间隔之间交换的若干次
所以结论就出来了
对所有数的位置差求一个共同gcd,找gcd的因数就可以了
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 int a[500005],b[500005]; 7 int pos[500005]; 8 int gcd(int a,int b){ 9 if(a<b)swap(a,b); 10 while(a=a%b)swap(a,b); 11 return b; 12 } 13 int g[100005]; 14 int main(){ 15 int n;cin>>n; 16 for(int i=1;i<=n;i++){ 17 cin>>a[i]; 18 pos[a[i]]=i; 19 b[i]=a[i]; 20 } 21 sort(b+1,b+n+1); 22 int s=0; 23 int last=0; 24 for(int i=1;i<=n;i++){ 25 if(i==pos[b[i]])continue; 26 if(!last)last=abs(pos[b[i]]-i); 27 else last=gcd(last,abs(pos[b[i]]-i)); 28 } 29 for(int i=1;i*i<=last;i++){ 30 if(last%i==0){ 31 g[++s]=i; 32 } 33 if(last/i!=i)g[++s]=last/i; 34 } 35 cout<<s<<endl; 36 for(int i=1;i<=s;i++)cout<<g[i]<<" "; 37 return 0; 38 }
over