2019 Multi-University Training Contest 5 - 1007求全排列

            http://acm.hdu.edu.cn/showproblem.php?pid=6630

 

permutation 2

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 354    Accepted Submission(s): 192


 

Problem Description

You are given three positive integers N,x,y.
Please calculate how many permutations of 1∼N satisfies the following conditions (We denote the i-th number of a permutation by pi):

1. p1=x

2. pN=y

3. for all 1≤i

 

 

Input

The first line contains one integer T denoting the number of tests.

For each test, there is one line containing three integers N,x,y.

* 1≤T≤5000

* 2≤N≤105

* 1≤x

 

Output

For each test, output one integer in a single line indicating the answer modulo 998244353.

 

 Sample Input

3 
4 1 4 
4 2 4 
100000 514 51144

 Sample Output

2 1 253604680

 

 

 

WA的代码(dfs暴力,仅用来产生数据来推理下面的公式):

#include
#include
#include
#include
using namespace std;
int ans[500000];
int cnt;
bool vis[500000];
int N,x,y;

void dfs(int num,int pos,int step) {
    if(vis[num]) return;
    if(pos >= N) return;
    if(pos == N-1){
        if(abs(num-y) > 2){
            return;
        }
    }
    
    ans[pos] = num;
    vis[num] = true;
    step++;                                                                                            
    if(step == N-2) {
        cnt++;
        vis[num] = false;
        step--;
        for(int i = 1;i <= N;i++){
            cout << ans[i] << " ";
        }
        cout << endl;
        return;
    }
    for(int k = num-2;k <= num+2;k++){
        if(k == num || k < 1 || k > N || k == y || vis[k]) continue;
        dfs(k,pos+1,step);
    }
    step--;
    vis[num] = false;
}

int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        memset(vis,false,sizeof(vis));
        memset(ans,0,sizeof(ans));
        cnt = 0;
        scanf("%d%d%d",&N,&x,&y);
        ans[1] = x;
        ans[N] = y;
        vis[x] = vis[y] = true;
        int step = 0;
        for(int j = x-2;j <= x+2;j++){
            if(j == x || j < 1 || j > N || j == y || vis[j]) continue;
            dfs(j,2,step);        //num   ans`s pos
        }
        printf("%d\n",cnt % 998244353);
    }
}


 

分析:2019 Multi-University Training Contest 5 - 1007求全排列_第1张图片

斐波那契数列     

1  1  1  2  3  4  6  9  13  19  28 ...........

然后对照下面核心代码那里就知道为什么跟斐波那契数列有关了

 

 

AC代码如下:

#include
#include
#include
using namespace std;
#define ll long long
const ll maxn = 1e6 + 10;
const ll MOD = 998244353;
int a[maxn];

void init(){
    for(int i = 3;i < maxn;i++){
        a[i] = a[i-1] + a[i-3];
        if(a[i] >= MOD){
            a[i] -= MOD;
        }
    }
}

int main(){
    int T;
    cin >> T;
    a[0] = 0;
    a[1] = a[2] = 1; 
    init();
    while(T--){
        int N,x,y,l,r;
        scanf("%d%d%d",&N,&x,&y);
        if(x == 1){
            l = 1;
        }else{
            l = x+1;
        }
        if(y == N){
            r = N;
        }else{
            r = y-1;
        }                                             // 然后求 [l,r]数字的全排列的种数 
                                                    //然而该种数竟然跟 斐波那契数列有关; 公式如右: f(i) = f(i-1) + f(i-3)       0  1   1   1  2   3   //                                                                                                                                                         4  6   .......
        if(x != 1 && y != N){                 //核心代码
            printf("%d\n",a[y-x-1]);
        }else if(x == 1 && y == N){
            printf("%d\n",a[y]);
        }else if(x == 1 && y != N){
            printf("%d\n",a[y-1]);
        }else if(x != 1 && y == N){
            printf("%d\n",a[y-x]);
        }                                        //核心代码
    }
    return 0;

你可能感兴趣的:(2019 Multi-University Training Contest 5 - 1007求全排列)