zoukankan      html  css  js  c++  java
  • Codeforces Lucky Permutation Triple

    构造类问题,打表找规律

    题意:输入n,生成一个n的全排列a,生成一个n的全排列b,从第1位到第n位,每个位上的对应的(ai+bi)%n=ci,然后得到n位的序列c,看看c是不是也是一个n的全排列,是的话就成功了,输出。如果无论怎样都找不到合适的a和b去构造出c,那么就输出-1

    这题一想通了,仅是那么的水,但是自己还是很长时间去思考

    说说思考的过程

    1.很容易想到,题目是想我们我们构造一个合适的a,b,进而产生合适的c,虽然题目让我们输出任意一个合法的排列就可以了,但其实要我们找的不是排列方案,而是匹配方案

    试想一下,如果手头上有合适的一个排列,那么我们把对应的ai,bi,ci捆版在一次,我们完全可以对这个排列进行重新排列(重新排列时,捆版的元素要一起移动),这样我们可以重新排除n!个排列,都是合法的,因为对应位在一起。

    所以我们得到一个结论,要么无解,要是有解的话,解的个数至少为n!(对于n=1也成立,n=1比较特殊,就是0 0 0),因为可能存在多种匹配方案

    2.有上面的结论远远不够解题,这时候我就想用暴力先打表看看当n较小的时候会有什么规律可循,但是没有电脑就一直手写。终于推到8的时候,发现n为偶数的时候都是无解,后来用电脑暴力打表也证实了这个规律

    3.但是对于n为奇数的情况,还是没有一个很好的解决方案,最终还是靠电脑打表,才发现了这是个水题,只要a和b都是0 1 2 3 4……n-1的时候,就必然是一个可行解

    所以就这样解决了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 100010
    
    int main()
    {
        int n;
        cin >> n;
        if(!(n&1)) cout << -1 << endl;
        else
        {
            for(int i=0; i<n; i++) cout << i << " "; cout << endl;
            for(int i=0; i<n; i++) cout << i << " "; cout << endl;
            for(int i=0; i<n; i++) cout << (2*i)%n << " "; cout << endl;
        }
        return 0;
    }

    打表程序

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 100010
    
    int a[N],b[N],c[N];
    bool ok,usedb[N],usedc[N];
    
    void dfs(int n,int cur)
    {
        if(cur >= n) 
        {
            ok =true;
            cout << "可行解" << endl;
            for(int i=0; i<n; i++) cout << a[i] << " "; cout << endl;
            for(int i=0; i<n; i++) cout << b[i] << " "; cout << endl;
            for(int i=0; i<n; i++) cout << c[i] << " "; cout << endl;
            return ;
        }
        for(int i=0; i<n; i++)
            if(!usedb[i] && !usedc[ (a[cur]+i)%n ])
            {
                usedb[i] = usedc[ (a[cur]+i)%n ] = true;
                b[cur] = i; c[cur] = (a[cur]+i)%n;
                dfs(n,cur+1);
                usedb[i] = usedc[ (a[cur]+i)%n ] = false;
            }
    }
    
    void solve(int n)
    {
        memset(usedb,false,sizeof(usedb));
        memset(usedc,false,sizeof(usedc));
        for(int i=0; i<n; i++) a[i] = i;
            
        dfs(n,0);  
        if(!ok) cout << "无解" << endl;    
    }
    
    int main()
    {
        freopen("BF.txt","w",stdout);
        for(int n=1; n<=10; n++)
        {
            printf("%d:_______________\n",n);
            solve(n);
            cout << endl;
        }
        return 0;
    }
  • 相关阅读:
    面试官:Redis 有哪些拓展方案?
    面试官:为什么要合并 HTTP 请求?
    Java 调用第三方接口,实战来了!
    Java 如何模拟真正的并发请求?
    如何搭建一台永久运行的个人服务器?试试这个黑科技!
    vs2005 sp1 出来啦!!
    2007年第一帖
    xp pro sp2支持多个用户同时终端连接
    msn中实现 "添加一个活动或游戏邀请"
    softether
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3131696.html
Copyright © 2011-2022 走看看