【数论】我们的可可西里

先说一句题外话 好久没更博客了。。。 希望自己不要退役 rp++
最近在学校学组合数学的时候碰巧做了一道题是这样描述的:
一共有4个格子和 1 2 3 4共4个数,要求第一个格子不填1,第二个格子不填2………………求一共有几种填法? 答:9种(数出来的。。。

然后才猛然发现,这题好像在哪见过?(你记得吗 然后写下了这篇博客。。。

【问题描述】

转眼到了2008年的6月9日,盼望已久的高考结束了。我们踏上了向西的旅程(本来是想写西去之路,可是考虑不太妥当)。可可西里,多么诱人的名词,充满了奇幻的色彩和自然的淳朴。从可可西里徒步走回家的决定是在1年半前定下的,而现在,终于可以实现那个钩过手指的预定。我们的可可西里。。。
在回家的路上,疯子和蚊子看到了许多可爱的藏羚羊,无意之中疯子和蚊子发现藏羚羊的居住地的分布也是有规律的,虽然疯子和蚊子早就听说藏羚羊是一种群体性很强又有超高IQ的动物,但是还是为它们的居住地分布规律感到惊叹。经过细心的观察,疯子和蚊子发现,如果假设一个藏羚羊群体有N只羊,就可以把它们的领地当做一个N*N的方阵,在这个方阵上第I列的第I 行都有一个圣地,它们不会居住在圣地,同时每行每列只能居住一只羚羊。于是他们很快算出一个有N只羊的藏羚羊群体的居住地分布方法数。

【问题分析】

相信dalao您也看出来了 题中这道题与上面的那道题是等效的,也就是说圣地的存在就相当于上文的限制条件,所以一起来研究这俩个问题。

那么如何确定 F(n) 呢?

我们就n= 4 的情况来研究(单纯的因为这是样例。。。

这里写图片描述

那么我们考虑F(i)作为一个递推函数来探究性质
F(n)=?F(n1)??

那么多出的一行对答案的影响是什么呢?我们不妨假设我们将第 n 行的放置在了位置x(x!=n)上。

Part1
若原来在第 x 列上的放到了第n列的格子上,那么相当于已经确定了 2 个,那么共有F(n2)种方案。因为就相当于去掉了第 x n列,再合起来形成一个 (n2)(n2) 的矩阵,等效于 F(n2)

Part2
若原来在 x 上的没有放到最后面的格子上,那么相当于前n1行中有一行被占用,但是又多出来一个可选位置即 n ,那么就有F(n1)种方案,因为将任意一种方案中原应放在 x 上的格子放在第n列就可以了。

所以递推式是 F(n)=(n1)(F(n1)+F(n2)) x 共有n1种取值)
需要上高精度,代码写的其丑无比,别打窝……

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int L=3001;
struct bign {
    int num[L]; int len;
    bign(){memset(num,0,sizeof num);}
    bign operator * (const bign &a) const{
        bign b;
        for (int i=0;i<=len;i++)
            for (int j=0;j<=a.len;j++)
                b.num[i+j]+=(num[i]*a.num[j]);
        b.len=a.len+len;
        for (int i=0;i<=b.len;i++)
        {
            b.num[i+1]+=(b.num[i]/10);
            b.num[i]%=10;
        }
        if (b.num[b.len+1]) b.len++;
        return b;
    }
    bign operator + (const bign &a) const{
        bign b; int p=max(len,a.len);
        for (int i=0;i<=p;i++)
            b.num[i]=num[i]+a.num[i];
        b.len=p;
        for (int i=0;i<=b.len;i++)
        {
            b.num[i+1]+=(b.num[i]/10);
            b.num[i]%=10;
        }
        if (b.num[b.len+1]) b.len++;
        return b;
    }
    void print(){
        for (int i=len;i>=0;i--)
            printf("%d",num[i]);
        printf("\n");
        return;
    }
    void pl(){
        num[0]++;
        for (int i=0;i<=len;i++)
        {
            if (num[i]>9)
                num[i+1]++,num[i]-=10;
            else break;
        }
        if (num[len+1]) len++;
        return;
    }
}a[2],z;
int n;
int main()
{
    scanf("%d",&n);
    if (n==1) printf("0\n");
    else if (n==2) printf("1\n");
    else {
        a[0].num[0]=1,a[0].len=0;
        a[1].num[0]=2,a[0].len=0;
        z.num[0]=3,z.len=0;
        int now=1,last=0;
        for (int i=4;i<=n;i++)
        {
            swap(now,last);
            a[now]=(a[last]+a[now])*z;
            z.pl();
        }
        a[now].print();
    }
    return 0;
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值