【SDOJ 2724】队列

【题目】

题目描述:

有 n 个不同的数列成一个队列,现在可以若干次选择两个数交换位置,每个数只能被交换一次。现在 L 想知道能得到多少种不同的队列。

输入格式:

第一行是一个整数 T,表示有 T 组数据

接下来 T 行,每一行是一个整数 N 表示数量

输出格式:

输出 T 行,每行一个正整数表示这组数据的答案(模 1e9+7 的值)

样例数据:

输入
2
2
3

输出
2
4

备注:

数据规模与约定:
20% 的数据,N ≤ 10
40% 的数据,N ≤ 1000
60% 的数据,N ≤ 50000
100% 的数据,1 ≤ N ≤ 1000000,1 ≤ T ≤ 100000
数据中均匀分布着 50% 的数据满足T ≤ 5

【分析】

首先看到题面,再看到数据范围,嗯,这是一道递推的题没跑了

emmm……本蒟蒻不太喜欢递推的题因为一般我都要推很久或者根本推不出来

做递动规的时候,如果自己想不出递推式,就要用一些神奇的方法,比如说自己暴力找出小数据的值,对这些值找规律(本蒟蒻就经常这么搞),一般运气好的话还是很容易找到规律的

下面是正解的推导:

我们用 f [ i ] 表示有 i 个数时的方案数,那么最后的答案 answer = f [ n ]

推到 f [ i ] 时,有如下两种情况:

  1. 第 i 个数和前(i - 1)个数没有交换,f [ i ] 加上 f [ i - 1 ]
  2. 第 i 个数和前(i - 1)个数中的某一个交换了,f [ i ] 加上 (i - 1)* f [ i - 2 ]

所以最后的递推式就是 f [ i ] = f [ i - 1 ] + (i - 1)* f [ i - 2 ]

【代码】

递推式都出来了,AC 还会远吗~

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000005;
const int mod=1e9+7;
long long f[N];
int main()
{
//	freopen("queue.in","r",stdin);
//	freopen("queue.out","w",stdout);
	int n,i,x;
	scanf("%d",&n);
	f[1]=1;
	f[2]=2;
	for(i=3;i<=N;++i)
	  f[i]=(f[i-1]+(i-1)*f[i-2])%mod;
	for(i=1;i<=n;++i)
	{
		scanf("%d",&x);
		printf("%lld\n",f[x]);
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/81283327