标题:NKOJ 1144: 洗牌问题
只看楼主
leeco
Rank: 4
等 级:贵宾
威 望:10
帖 子:1026
专家分:177
注 册:2007-5-10
得分:0 
回复:(HJin)回复:(leeco)回复:(aipb2007)我那...

我认为只跟踪一个位置的牌的算法,被接受只是巧合,可能他测试数据设计的不好,或者这题的置换是置换的一个特例恰好跟踪1号位的牌都是正确的。

http://acm.pku.edu.cn/JudgeOnline/problem?id=2369
这题是一个更普遍的情况。我们可以看到对于它列举的一个情况
1 2 3 4 5
2 4 5 1 3

经过0次置换得到 1 2 3 4 5
经过1次置换得到 2 4 5 1 3
经过2次置换得到 4 1 3 2 5
经过3次置换得到 1 2 5 4 3 //这时1号位的已经回来了,但是 3 5号位的却没有。

2007-07-29 11:42
HJin
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:401
专家分:0
注 册:2007-6-9
得分:0 
回复:(leeco)回复:(HJin)回复:(leeco)回复:...

The permutation group can be represented by matrix A
of size 2n by 2n with

A(2,1)=A(4,2)=...=A(2n,n)=1;
A(1,n+1)=A(3,n+2)=...=A(2n-1,2n)=1;
A(i,j) = 0 if (i,j) does not belong to above cases.

I believe you can show that it is a cyclic group. You may need to study
the theory of groups.

Although leeco gave a counter-example for odd number (here we have 2n),
I believe that we can move the first number back to position 1 with all
other numbers simultaneously back to their original positions.


Following C++ code verifies that this observation holds for 1<=n<=10^3.

==========================================================
#include <iostream>
#include <iomanip>
#define N 1000
using namespace std;

int a[2*N+1], b[2*N+1];

void shuffle(int*a, int *b, int n)
{
int i, i2;
for(i=1; i<=n; ++i)
{
i2=(i<<1);
b[i2] = a[i];
b[i2-1] = a[n+i];
}
}

int count(int n)
{
int i, c=0, n2=(n<<1);
bool bOrig = false;

for(i=1; i<=n2; ++i)
a[i] = i;

while(!bOrig)
{
shuffle(a, b, n);
++c;
bOrig = true;
for(i=1; i<=n2; ++i)
{
if(b[i] != i)
{
bOrig = false;
break;
}
}
if(bOrig)
break;

shuffle(b, a, n);
++c;
bOrig = true;
for(i=1; i<=n2; ++i)
{
if(a[i] != i)
{
bOrig = false;
break;
}
}
}

return c;
}

int permute1(int n)
{
int a=2, c=1;

while(a!=1)
{
if(a<=n)
a<<=1;
else
a=2*(a-n)-1;
++c;
}

return c;
}

int main()
{
int n;

for(n=1; n<=N; ++n)
{
// If you have access to nice computing service, change N to a big
// number and run it.
//
// If you are a math graduate, show it mathematically that there eixsts
// k s.t. A^k = I.

if( count(n) != permute1(n) )
cout<<setw(6)<<n<<setw(10)<<count(n)<<setw(10)<<permute1(n)<<endl;
}

return 0;
}


I am working on a system which has no Chinese input. Please don\'t blame me for typing English.
2007-07-29 13:28
leeco
Rank: 4
等 级:贵宾
威 望:10
帖 子:1026
专家分:177
注 册:2007-5-10
得分:0 
回复:(HJin)回复:(leeco)回复:(HJin)回复:(...

偶数仍然有反例,只不过对于位置1恰好是对的,可能是由于题目说的这种置换比较特殊。
对于20个元素的情况,我们看到经过6次置换1号位的元素第一次回答1号位,而恰好其他的元素也第一次回到了原来的位置
但是对于3号位,6号位,9号位,12号位,15号位,18号位已经是第2次回到原来的位置了。
而对于7号位,14号位已经是第3次回到原来的位置了。
如果换一种洗牌方式,就不能盲目的选择1号位作为考察的位置了,对于这题选择1号位正确,只是巧合

事实上是3,12,6独自成循环,9,15,18独自成循环,7,14独自成循环,1,11,16,8,4,2,独自成循环。
而1恰好在一个最大的循环里,并且这个循环是其他循环的最小公倍数。这是很特殊的。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
11 1 12 2 13 3 14 4 15 5 16 6 17 7 18 8 19 9 20 10
16 11 6 1 17 12 7 2 18 13 8 3 19 14 9 4 20 15 10 5
8 16 3 11 19 6 14 1 9 17 4 12 20 7 15 2 10 18 5 13
4 8 12 16 20 3 7 11 15 19 2 6 10 14 18 1 5 9 13 17
2 4 6 8 10 12 14 16 18 20 1 3 5 7 9 11 13 15 17 19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

[此贴子已经被作者于2007-7-29 17:03:03编辑过]

2007-07-29 16:56
crystaljing
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2007-7-19
得分:0 

各位怎么就这么厉害呢?!光把你们写的程序读懂都很不简单...........
真心谢谢你们!!


好好享受我的大学生活~~~
2007-07-31 16:04



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-158622-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.104424 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved