@UPC 6887 @【JXOI2018】游戏 (组合+线性筛)

题目描述

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

 

求的是 总和, 不是期望

线性筛 非倍数个数 cot, 组合公式求 结果  n = r-l+1  区间长度

\sum_{cot}^{n} cot* i! *\frac{(n-cot )!}{(i-cot)!}

 

然后 按照公式 逆元 + 阶乘 瞎搞一波,  

 

[代码]

#include <iostream>
#include <bits/stdc++.h>

#define rep(i,a,n) for(ll i = a;i<n;i++)
#define per(i,a,n) for(ll i = n-1;i>=a;i++)
typedef   long long ll;
typedef unsigned long long llu;

const int mod = 1e9+7;
const int MAXN= 2e7+150;
using namespace std;

inline ll qpow(ll a,ll n)
{
    ll ans = 1;
    for(;n;n>>=1)
    {
        if(n&1)
        {
            ans = (ans*a) %mod;
        }
        a = (a*a) %mod;
    }
    return ans;
}

ll n,cot;
int vis[MAXN];
ll inv[MAXN];
ll fac[MAXN];
ll l, r;
void init()
{
    cot = 0;
    rep(i,l,r+1)
    {
        if(vis[i])
            continue;
        cot++;
        for(ll j=2;j*i<=r;j++)
            vis[i*j]=1;
    }
}
void work()
{
    fac[0] = 1;
    rep(i,1,n+1)
        fac[i] = (fac[i-1]*i )%mod;
    inv[n-cot] = qpow(fac[n-cot],mod-2);
    for(ll i = n-1-cot; i>=0 ;i--)
        inv[i] = ( inv[i+1]*(i+1) ) %mod;
    ll ans = 0;
    rep(i,cot,n+1)
        ans = (ans + ( ((cot*fac[i])%mod *fac[n-cot])%mod*inv[i-cot])%mod)%mod;
    cout<<ans<<endl;
}
int main()
{
    scanf("%lld %lld",&l,&r);
    n = r-l+1;
    init();
    work();
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值