unsigned long gcd(unsigned long a, unsigned long b);
void __lshift(int *a, unsigned n, unsigned k)
{
unsigned d;
unsigned q;
int i,j,s,m;
d = gcd(k, n);
q = n/d - 1;
for(i=0; i<d; i++){
int t = a[i];
for(j=0,s=i; j<q; j++){
m = (s+k)%n;
a[s] = a[m];
s = m;
}
a[(n-k+i)%n] = t;
}
}
void lshift(int *a, unsigned n, unsigned k)
{
if(k>=n)
k = k%n;
if(k==0)
return;
__lshift(a, n, k);
}
void rshift(int *a, unsigned n, unsigned k)
{
if(k>=n)
k = k%n;
if(k==0)
return;
__lshift(a, n, n-k);
}
void print_a(int *a, unsigned n)
{
int i;
for(i=0; i<n-1; i++)
printf("%2d ", a[i]);
printf("%2d\n", a[n-1]);
}
int main(int ac, char *av[])
{
int a[] = {1,2,3,4,5,6,7,8,9,10,11,12,};
print_a(a, 12);
rshift(a, 12, 3);
print_a(a, 12);
return 0;
}
数组a[n]被k分为gcd(n,k)个集合,集合Si(i=0,1,...)的产生方式是:
1) i在集合Si;
2) 如果m在Si, 那么(m+k)%n 也在集合Si;
这样集合Si就可以以i,(i+k)%n, (i+2k)%n,...(i+mk)%n的方式遍历完。
可以证明a[n]被k分为gcd(n,k)个这样的Si(i=0,1,..n/gcd(n,k)-1),且|Si|=|Sj|,即任意两个集合Si的个数都相同