[递推]通话调研

Problem F: 通话调研

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 254   Solved: 36
[ Submit][ Status][ Web Board]

Description

 埃森哲的小Q最近在做市场调研,每天要打很多的电话。一天打的累了,正在喝咖啡休息。不过爱动脑筋的小Q的脑袋可没有闲着,他在思考这样一件事:如果一共有N个人(编号1-N),假设所有人都相互认识。每个人都拥有一部电话,且每时每刻他们都有可能在跟另一个人通话(当然也可以没有打电话而在干别的事情)。

我们假设每次通话只限于两人通话,则在某个时刻,我们突然检查所有人的状态,我们想知道所有人的通话状态数有多少种。举个栗子(为什么是栗子!):当前有2个人,则在某个时刻,我们突然检查这2个人的状态,则总共有2种情况,要么1号和2号在通话,要么各自在做着别的事情。
当然聪明的小Q想的问题不会这么简单,小Q还会给出更多的约束,即已知在检查的那个时刻,有M个人一定不在通话中。现在请你计算一下总的情况数。

Input

 多组测试数据。

对于每组数据:
第1行:输入两个整数N和M(1 <= N <= 1,000,000, 0 <= M <= N)。
第2行:输入M个整数Ai(1 <= Ai <= N)分别代表那些肯定不在通话的人编号,我们保证输入序列没有重复数。

Output

 对于每组数据,输出一行,包含一个整数,代表总的情况数。由于最后答案过大,请把答案对1,000,000,007(1e9 + 7)取模后输出。

Sample Input

2 122 0

Sample Output

12

HINT


定义函数F(x,y)为共n个人,有m个人一定没有打电话时,总的情况数。

发现,这m个人不会对剩下的人造成影响,而且他们只存在一种情况,都不打电话。

所以转化为,F(x,y) = F(x-y,0)。定义f(x) = F(x,0)


如何计算f(x)?

假设有序。若第x个人不打电话,则同上讨论结果,转化为相同子问题f(x-1)。若第x个人打电话,则他只能和剩余x-1个人中一个人打电话,有x-1种选择。并且这两个人都不能再和别人打电话,因此转化为相同子问题f(x-2)。则f(x) = f(x-1)+(x-1)*f(x-2)。


#include <cstdio>
#include <string>
#include <cstring>

inline int getint()
{
    int res=0;char tmp;bool sgn=1;
    do tmp=getchar();
    while (!isdigit(tmp)&&tmp!='-');
    if (tmp=='-'){sgn=0;tmp=getchar();}
    do res=(res<<3)+(res<<1)+tmp-'0';
    while (isdigit(tmp=getchar()));
    return sgn?res:-res;
}

typedef long long ll;

const ll MOD = 1000000007;
ll f[1000010];

int main()
{
    f[1] = 1;
    f[2] = 2;
    for (int i=3;i<=1000000;i++)
    {
        f[i] = (f[i-1] + (f[i-2] * (i-1))%MOD)%MOD;
    }
    int n,m;

    bool first = true;
    while (scanf("%d%d",&n,&m)==2)
    {
        if (!first)
            printf("\n");
        first = false;
        int tmp;
        for (int i=1;i<=m;i++) scanf("%d",&tmp);
        printf("%d",int(f[n-m]));
    }

	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值