史前文明 组合数学

史前文明

题目描述

明明和白白是好朋友,他们经常在一起商量数学问题。

明明和白白暑假到巨石阵旅游。他们发现这些巨石高大耸峙,而且以一种富含魔力的方式排列着。他们面前有n块石头,明明给他们编号为1~n。而恰巧编号为i的石头高度也为i。他们随后惊奇地发现这些石头可以挪动,于是他们定义一个石头的排列为“魔阵”,当且仅当这个排列中最少有n-k个石头满足它所处的位置等于它的高度,即ai=i;

明明明明明白白白白白浪费了一天的时间来搬石头,但他还是想计算一下一共有几种“魔阵”。

输入

有多组测试样例。每行两个数n和k,4<=n<=1000   1<=k<=4

输出

每行一个答案,输出魔阵的种类数量。

样例输入

4 1 
200 3
200 4
1000 4

样例输出

1
2646701
584811251
373086956251

分析:

很明显的错位排列题,由于k很小只有4,所以直接分类讨论一下就可以了,甚至暴力都可以完成。

k=1

只有一种,1,2,3,4........n,F[1]=1;

k=2

从n个数中选择2个,有C(n,2)种选法,选出的两个数交换一下,所以每种选法有1种情况,F[2]=F[1]+C(n,2);

      位置                   1                       2
  情况1(合法)                   2                       1
情况2(重复)                   1                       2

k=3

从n个数中选择3个,有C(n,3)种选法,选出的三个数有两种交换,所以每种选法有2种情况

F[3]=F[1]+F[2]+C(n,3)*2

位置 1 2 3
重复 1 2 3
重复 1 3 2
重复 2

3
合法 2 3 1
合法 3 1 2
重复 3 2 1

k=4

从n个数中选择4个,有C(n,3)种选法,选出的三个数有两种交换,所以每种选法有9种情况,F[4]=F[1]+F[2}+F[3]+C(n,4)*9

位置 1 2 3 4
1 2 1 4 3
2 2 3 4 1
3 2 4 1 3
4 3 2 4 1
5 3 1 2 4
6 3 1 4 2
7 4 1 2 3
8 4 3 1 2
9 4 3 2 1
#include<bits/stdc++.h>
using namespace std;
long long int n,k;
int main()  {
    while(~scanf("%lld %lld",&n,&k))
    {
        long long t=1;
        if(k==1)
        {
            printf("1\n");
        }
        t+=n*(n-1)/2;
        if(k==2)
        {
            printf("%lld\n",t);
        }
        t=t+n*(n-1)*(n-2)/3;
        if(k==3)
        {
            printf("%lld\n",t);
        }
        t=t+n*(n-1)*(n-2)*(n-3)*3/8;
        if(k==4)
        {
            printf("%lld\n",t);
        }
    }
    return 0;
}

关于 long long int(64位长整型)的输出

1<<63  错误,由于1默认是int型,左移63位后就会溢出

1LL<<63  正确,先把1转换为long long 型,然后左移63位就不会溢出啦

long long t=(1LL<<63);
printf("%lld\n",t);
printf("%lld\n",1LL<<63);

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/81748400