2015 百度之星1001搬家 组合问题

大搬家

 
 Accepts: 1516
 
 Submissions: 6288
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
Problem Description

近期B厂组织了一次大搬家,所有人都要按照指示换到指定的座位上。指示的内容是坐在位置 i 上的人要搬到位置 j 上。现在B厂有 N 个人,一对一到 N 个位置上。搬家之后也是一一对应的,改变的只有位次。

在第一次搬家后,度度熊由于疏忽,又要求大家按照原指示进行了一次搬家。于是,机智的它想到:再按这个指示搬一次家不就可以恢复第一次搬家的样子了。于是,B厂史无前例的进行了连续三次搬家。

虽然我们都知道度度熊的“机智”常常令人堪忧,但是不可思议的是,这回真的应验了。第三次搬家后的结果和第一次的结果完全相同。

那么,有多少种指示会让这种事情发生呢?如果两种指示中至少有一个人的目标位置不同,就认为这两种指示是不相同的。

Input

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

每组数据包含一个整数 N(1N1000000)

Output

对于每组数据,先输出一行 Case #i: 然后输出结果,对 1000000007 取模。

Sample Input
2
1
3
Sample Output
Case #1:
1
Case #2:
4

因为其实要找的数串是这样的,比如:
12345->21435
你发现没,如果1对应2,那么2必须对应13对应44必须对应3,那5就只能对应5了,就是找123.....N有多少个这样的对应关系,所以呀,要用组合数学中的加法原理,对于某一个数有两种情况,对应自己或者对应其他数,如果对应自己,那么剩下的就只有N-1个数了,如果对应的是别的数,那么被对应的数必须对应它,这样就只剩下N-2个数了,而这个数可以对应的其他数有N-1个,所以呀,f(n)=f(n-1)+(n-1)*f(n-2)

 

 

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define ll long long
const int  mod = 1e9+7;
const int N = 1e6+5;

ll a[N];
void fun()
{
    a[0] = a[1] = 1;
    for (int i = 2; i <= N - 5; i++)
    {
        a[i] = (a[i - 1] + (i - 1) * a[i - 2]) % mod;
    }
}

int main()
{
    fun();
	int t;
	cin >> t;
	int cnt = 1;
	while (t--)
	{
		int n;
		cin >> n;
		printf("Case #%d:\n", cnt++);
		printf("%lld\n", a[n]);
	}
	
	return 0;
}


 



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值