[upcoj]6887: 游戏

时间限制: 1 Sec 内存限制: 512 MB

题目描述

九条可怜是一个热爱游戏的女孩子,她经常在网上和一些网友们玩一款叫做《僵尸危机》游戏。
在这款游戏中,玩家们会需要在成为僵尸之前与黑恶势力斗智斗勇,逃离被病毒感染的小岛。但是黑恶势力不会让玩家轻易得逞,他会把一些玩家抓走改造成僵尸。变成僵尸的玩家会攻击其他的玩家,被攻击的玩家会被”感染”,成为病毒的潜在宿主。
具体来说,游戏开始时,所有的玩家会获得一个L∼R的编号(如果一共有R−L+1个玩家),不同的玩家的编号不同。
游戏分轮次进行,在每一轮中一次会发生这样的事情。
•如果所有当前所有的正常人都已经被感染,那么游戏结束。
•不然,黑恶势力会在当前的正常人(包括被感染的人)中等概率随机一个改造成僵尸。
•被改造成僵尸的玩家会攻击所有编号是他的倍数的玩家,使得他们被感染。
九条可怜现在想知道,这个游戏期望会进行多少轮?这个答案可能是一个实数,她想让你给出期望轮数乘上(R−L+1)!以后的结果,这个结果可能很大,请对10^9+7取模后输出。

输入

第一行输入两个整数 L, R 表示编号范围。

输出

一个整数,表示期望进行的轮数。

样例输入

2 4

样例输出

16

提示

• 2 3 4, 轮数是 2。
• 3 2 4, 轮数是 2。
• 4 2 3, 轮数是 3。
• 4 3 2, 轮数是 3。
• 2 4 3, 轮数是 3。
• 3 4 2, 轮数是 3。
每种情况的概率都是 1/6,于是期望轮数就是 (2 + 2 + 3 + 3 + 3 + 3)/6 =8/3。
乘上 3! = 6 以后就是 16 。

对于 20% 的数据,R − L + 1 ≤ 8。
对于另 10% 的数据,L = 1。
对于另 10% 的数据,L = 2。
对于另 30% 的数据,L ≤ 200。
对于 100% 的数据,1 ≤ L ≤ R ≤ 107 。

来源/分类

江西OI2018

Solution

这是一道组合数学题。我觉得关键在于理解题意,细心分析。
对题意的补充说明和理解如下(感谢tb&&qg):
1.此处共有三类人,正常人、僵尸、被感染者;
2.成为僵尸与被感染的不同之处 : 僵尸可以感染正常人,被感染者不能感染正常人,被感染者可以被改造成僵尸;
3.僵尸感染正常人不消耗时间;
4.游戏只有在没有1个正常人的时候才结束,例如样例”2 4 3”是3轮——①选2改造成僵尸,同时2将4感染,3正常,游戏不结束;②选4(已被感染)改造成僵尸,3仍正常,游戏不结束;③3被改造成僵尸,没有正常人了,游戏结束。
重点在于用类似线性筛的方法求必须被改造的人数s,以及排列组合求ans。

Code
#include <cstdio>

const int MOD = 1000000007;
const int MX = 10000001;
int fac[MX];
long long tmp, ans;
bool vis[MX];
int l, r, n, s, p, i, j;

int main() {
    scanf("%d%d", &l, &r);
    fac[0] = fac[1] = 1;
    for (i = 2; i <= r; ++i) fac[i] = 1ll * fac[i - 1] * i % MOD;
    for (i = l; i <= r; ++i)
        if (!vis[i]) {
            s++;
            for (j = 1; j * i <= r; ++j) vis[j * i] = 1;
        }
    n = r - l + 1;
    tmp = 1;
    p = n - s;
    for (i = n; i >= s; --i) {
        ans = (ans + fac[i] * tmp) % MOD;
        (tmp *= p--) %= MOD;
    }
    (ans *= s) %= MOD;
    printf("%lld\n", ans);
    return 0;
}
/************************
    Time:392 ms
    Memory:49920 kb
*************************/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值