CF#303A Lucky Permutation Triple 数论

题意:要求给出一个数N的余数系的三个排列A, B, C,其中使得对于任意的 i 满足(A[i] + B[i]) % N = C[i]。

例如N=5的时候有一下排列:

A: 1 4 3 2 0
B: 1 0 2 4 3
C: 2 4 0 1 3

解法:首先排列如果存在的话,肯定是不唯一的,因为可以随意交换A,B,C的相同两列使得结果仍然满足。对于一个给定的N,我们可以列出一下一张图:

横纵坐标反应了余数相加的情况:
0 1 2 3 4
1 2 3 4 0
2 3 4 0 1
3 4 0 1 2
4 0 1 2 3
只要取从左上到右下的对角线即可。

以上只能够保证N为奇数的时候有解,不足以说明白偶数为何无解。还有一种观点现在自己还证不出来:对于每一种合法的情况,A,B,C一定是按照某种规则增长的,也就是一个等差数列,只是每一位数都对N取模而已。那么如果公差d于N互质的话,能够在N步之内枚举完所有的余数,否则不能。

证:任何一个序列如果从0开始,那么序列就变为了0, d%N, 2*d%N ... i*d%N ... j*d%N...(N-1)*d%N 如果存在id % N = jd % N,那么N | (j-i)d,由于gcd(d, N) = 1 且 i-j < N,这显然是荒谬的。所以任意两个id%N, jd%N都是互质的,因为有N个数,所以也就取遍了所有的余数,而对于于N不互质的d,则无法推导出次结论,实际上只要 j-i = N/gcd(d,N)时,就有id%N = jd%N了,显然可以找到这样两个余数相同的数。

这也就是为什么上面取A,B序列公差均为1可以的原因了,因为两个公差为1的序列相加之后公差为2,而2与奇数N是互质的。因此还可以选择更多的方案来完成匹配。如果上面的假设成立,那么对于偶数N也是很好否定的,因为偶数N的A,B所取得两个公差一定要求都是奇数,而如此对于C而言则公差变成了偶数,此时N也为偶数,由于d于N不互质,也就无法构造出这样三个序列了。

现在我无法证明的就是为什么在对A做一个排序使其成为d=1的序列后,一定要求B也同样为一个等差序列。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;

int main() {
    int N;
    while (scanf("%d", &N) != EOF) {
        if (!(N&1)) {
            puts("-1");
            continue;    
        }
        for (int i = 0; i < N; ++i) {
            printf(i == N-1 ? "%d\n" : "%d ", i);
        }
        for (int i = 0; i < N; ++i) {
            printf(i == N-1 ? "%d\n" : "%d ", i);
        }
        for (int i = 0; i < N; ++i) {
            printf(i == N-1 ? "%d\n" : "%d ", 2*i%N);
        }
    }
    return 0;    
}

 

转载于:https://www.cnblogs.com/Lyush/archive/2013/05/13/3075939.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值