uvalive 5971 解题报告(找规律+推理)

本文介绍了一个有趣的问题:如何计算在前N个自然数的所有排列中,不包含相邻的x和x+1(1≤x<N)的有效排列的数量,并给出了解决方案的递推公式及AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Permutation Counting
Dexter considers a permutation of first N natural numbers good if it doesn't have x and x+1 appearing cons ecutively, where (1 ≤ x < N). For example, for N=3, all good permutations are:
1.{1, 3, 2}
2.{2, 1, 3}
3.{3, 2, 1}
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.Each case starts with a line containing an integer N (1 ≤ N ≤ 10^6).
Output
For each case, print the case number and the number of good permutations modulo 1000000007.
Sample Input
3
2
3
5
Sample Output
Case 1: 1
Case 2: 3
Case 3: 53


解析:

这题主要是求递推公式:

递推公式为:f(n)=f(n-1)*(n-1)+f(n-2)*(n-2)      -----下面来解释解释

f(n)可以建立在f(n-1)的基础上插入n这个数的操作以及不同于这个的操作的两个部分

想想为什么会这样呢,因为f(n)对于f(n-1)数量上只是多出了一个数字n,那么他多出的情况又有多少呢?

首先是在f(n-1)的基础上插入n形成新的符合条件的排列,还有对于n-1时只有一个x ,x+1(因为数字n只能破坏一个x,x+1)的情况(下面举例),只要把n插入到x与x+1之间,就能形成新的符合条件的排列,这是f(n-1)所没有的排列

如  1 2 4 3  只有一个x,x+1中情况即1,2,       在1,2之间插入5成为     1  5 2 4 3

      4 3 1 2        这个也是只有一个x,x+1,                        插入5  后         4 3  1 5 2

还有其他只有一个x,x+1的就不一一举例了

下面以n=5为例

  1. 对于f(n-1)*(n-1)这部分,
           假设 f(4) 已知,那么对于n=4时的每一种排列(共f(4)种),5插入的位置有5个但数字4的后面不能插数字5,故有四个位置可插,故总数为 f(4)*4
           对于一般情况的n,则为f(n-1)*(n-1)

  2. 对于f(n-2)*(n-2) 这部分,这部分可能比较难理解,上面的红字讲到对于n-1时只有一个x ,x+1(因为数字n只能破坏一个x,x+1)
    的数量就是f(n)-f(n-1)*(n-1),我们只要证明其等于f(n-2)*(n-2)即可
    我们可以把这里的x,x+1看成x,然后将x+2,x+3,......,n-1;都减1,变成x+1,x+2,.......n-2,这排列的数量就是f(n-2);
    而对于n-1,x,x+1的情况与n-2个,以n=5为例有,对于4来说,有(1,2),(2,3),(3,4)三个即(n-2)个
    故f(n)-f(n-1)*(n-1)=f(n-2)*(n-2);

ac代码:

#include<cstdio>
#include<string.h>
#include<stack>
#include <cstdio>
#include <iostream>
using namespace std;
#define ll long long
ll a[1000003];
int main()
{
    //f(n)=f(n-1)*n-(n-3)
    int t;
    int n;
    a[1]=1;
    a[2]=1;
    for(int i=3;i<=1000000;++i)
        a[i]=(a[i-1]*(i-1)+a[i-2]*(i-2))%mod;

    scanf("%d",&t);
    for(int w=1;w<=t;++w)
    {
        scanf("%d",&n);

        printf("Case %d: %d\n",w,a[n]%mod);


    }

	return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值