HDU 2068 RPG错排

1.题意:1到N的序列的排列中,元素位置与元素值相对应的情况(值为i的元素在某个排列中正好排在第i个位置)大于等于序列规模一半的情况,有多少个?

2.输入输出:每组数据一个数,N,规定输入以0结尾;

3.分析:原题意换句话说,就是针对1到N的全排列,错排元素的个数小于等于N的情况有多少;

那么,输出即为:

,其中F[i]表示1到i的错排方案数,后面一项为组合数,即选取i个错排;

这里推导一下错排公式,F[N]表示1到N的错排方案;第一步:选取N放到1到N-1之中任意一个位置,这样就有N-1种放法;第二步:分两种情况,不妨设第一步被N占据的位置为K,当位置N放置的数恰巧为K时,此时就相当于,K,N交换位置了,对应的错排方案为F[N-2];当位置N放置的数不为K时,此时的情况:1到K-1,K+1到N的位置要错排放置1到N-1的元素,N-1个 位置,N-1个元素,与F[N-1]的情况相比,只是多了一组(数K与位置N)的对应,而且这里N不放置K,就等效于普通的情况下(数K与位置K)的错排情况;举个例子,位置12345,数12345,现在5放置在2的位置上,剩下数1234,位置1345,且位置5上不放2,这里和1234-1234的错排有什么区别么?把位置5当成位置2,反正也是2不放在位置5上,与1234-1234里2不放在位置2上等效;综上所述,错排公式为F[i]=(i-1)*(F[i-1]+F[i-2]),其中,F[1]=0,F[2]=1;

转载于:https://www.cnblogs.com/cnXuYang/p/6665269.html

import java.util.Scanner;

public class hdu2068 {
    public static long C(int n,int m){
        if(m==0){
            return 1;
        }
        long res = 1;
        for (int i = n-m+1; i <= n; i++) {
            res *= i;
        }
        for (int i = 1; i <= m; i++) {
            res /= i;
        }
        return res;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long[] f = new long[13];
        f[0] = 1;
        f[1] = 0;
        for (int i = 2; i < f.length; i++) {
            f[i] = (i-1)*(f[i-1]+f[i-2]);
        }
        long[] kk = new long[26];
        for (int i = 1; i <= 25; i++) {
            kk[i] = 0;
            for (int j = 0; j <= i/2; j++) {
                kk[i] += f[j]*C(i,j);
            }
        }
        while (sc.hasNext()){
            int n = sc.nextInt();
            if (n==0){
                break;
            }
            System.out.println(kk[n]);
        }
    }
}

 

posted @ 2025-02-17 19:35  XiaohuangTX  阅读(8)  评论(0)    收藏  举报