码迷,mamicode.com
首页 > 其他好文 > 详细

BestCoder 百度之星

时间:2016-05-10 12:33:56      阅读:332      评论:0      收藏:0      [点我收藏+]

标签:

2016 0510 百度之星测试赛

大搬家

 
Problem Description

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

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

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

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

Input

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

每组数据包含一个整数N(1 \leq N \leq 1 000 000)N(1N1000000)。

Output

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

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

思路:直接想的可能是怎么才能搬家三次的结果和搬家一次的结果相同,但是实际上可以简化为搬家两次的结果和搬家之前相同。
要出现这样的情况,那第一次搬家i-j必须满足i==j或者i-j&&j-i(i!=j).
当给定为N个人搬家时有ans[N]种满足条件的可能,假设第一个人是1-1,也就是位置不变,那么剩下的人可能的情况就是ans[N-1]种。
当第一个人是1-j(j!=1)时,那么必定有j-1。所以还剩下N-2个人,所以就是ans[N-2],又因为此时j有N-1(2-N)种可能。
可得出dp公式 ans[N] = ans[N-1] + (N-1)*ans[N-2];
初始值ans[1] = 1;ans[2] = 2;利用递归或者dp即可解决,但是递归会超时,dp才是正道。
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int t = sc.nextInt();            
            long[] ans = new long[1000001];
            long mod = 1000000007l;
            ans[1] = 1;
            ans[2] = 2;
            int m = 3;
            for (int i = 1; i <= t; i++) {
                int n = sc.nextInt();                
                while (m <= n) {
                    ans[m] = mod(ans[m-1] + (m-1)*ans[m-2]); //用mod函数会稍微快点,但是不影响结果
                    m++;
                }
                System.out.println("Case #"+i+":");
                System.out.println(ans[n]);
//             System.out.println("Case #"+i+":\n"+ans[n]);//这种形式会报格式错误
            }
        }
    }
    public static long mod(long i) {
        return i%1000000007;
    }
}

/**TLE 递归影响时间,改成dp

public static int find(int n) {
    if (n == 1)
        return 1;
    if (n == 2)
        return 2;
    else 
        return mod(find(n-1))+mod((n-1)*find(n-2));            
}
*/


代码中的斜体部分应该放到for循环外,这样就可以保存ans[]数组的结果,在下一个测试用例时就可以直接利用了,如果放在for循环内,就会超时。

ps: 最后的打印换成代码中的另一种形式就会格式错误Presentation Error,不知道为什么。

 

BestCoder 百度之星

标签:

原文地址:http://www.cnblogs.com/fisherinbox/p/5477272.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!