2019杭电多校 第五场 6630(原1007) permutation 2 (斐波那契数列)

2019杭电多校 6630(原1007) permutation 2 (斐波那契数列)

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

大致题意:

输入时候给你n,x,y三个正整数,n表示有n个互不相同数字(范围:[1,n]),x是第一个数字,y是末尾的数字,让你排列填满中间的数字,并且任意两项之差的绝对值小于等于2,问你有多少种排列组合。

思路:

一开始以为这是一道排列组合题,然而最后自闭了。其实只要有耐心多写几组数据,就能看出规律了(或者直接写一个暴力(DFS)代码模拟一下找几组数据来分析)。实际上是一个类似斐波那契数列的规律。下面举几个例子来展示:

列举1~n的排列,第一位为1,最后1位为n:

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

假设以data[i] 数组储存以1为首位,i为末尾这样排列组合数量的话,那么根据上面的截图举例可以得到
data[2] = data[3] = 1;
data[4] = 2;
data[5] = 3;
data[6] = 4;
data[7] = 6;
data[8] = 9;
data[9] = 13;
data[10] = 19;

这样就可以看出规律了:
data[i] = data[i - 1] + data[i - 3] ;

不过这只是以1为首位,n为末尾的组合排列的规律。
接下来随便取几组数据看,这里我只举一个例子来说明:
令n=20, x = 5, y = 15
在这里插入图片描述
根据 1号红框 里的数据可以发现:
数列是固定从x降低到1,然后再增加到6。

同理根据 2号红框 数据发现:
数列末尾固定从y提升到n,然后降低到14

中间 这部分是排列组合,一共有 7 个数字在排列组合,而且排列组合数正好为 data[9] = 13 !回顾我们之前是如何得到 data[9] 的?恰好也是 1和9 分别为头尾两个数固定不动,中间部分 7个数字排列组合

那么最后就可以得到这道题的解法:

第1步:得到data[] 数列
第2步:根据输入的n, x, y 计算出排列后,1、2号红框部分固定的数字数量
第3步:计算出中间部分数字的数量 k
第4步:data[k + 2] 即为答案

代码部分:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string.h>
#include<algorithm>
using namespace std;
const int MOD = 998244353;
const int maxn = 1e6 + 5;
long long data[maxn];

void fb() {
	data[0] = data[1] = data[2] = data[3] = 1;
	//如果没有答案的话,要输出 0 ,比如输入 10 2 3 
	data[0] = 0;
	for(int i = 4; i <= maxn; i++) {
		data[i] = data[i-1] + data[i-3];
		data[i] %= MOD;
//		printf("data[%d] = %d\n", i, data[i]);
	}
}

int main() {
	int t;
	fb();
	while(~scanf("%d",&t)) {
		while(t--) {
			int n, x, y;
			scanf("%d %d %d",&n, &x, &y);
			
			//其实x++正好就是1号红框从左往右最后一位数字
			//前提是 x != 1
			if(x != 1)
				x++;
			//同理y++就是2号红框从左往右数第1位数字
			if(y != n)
				y--;
			
			printf("%lld\n", data[y - x + 1]);
		}
	}
	return 0;
}

总结:

果然我是菜得不行,日常被签到题搞自闭,如果能多写出几组数据的话,或者写出暴力dfs代码就能找出规律做出这道题了,然而我写不出数据也写不出代码2333333被自己菜哭了,补题的时候找zqw学长(感谢各位学长了)要来DFS的代码才找出来的,后面自己写一下dfs代码再贴上来这里吧!加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值