洛谷P4562 [JXOI2018]游戏 (Bzoj 5323)(Upc 6887)游戏

题目链接:https://www.luogu.org/problemnew/show/P4562 (不开氧气就RE,不知道为啥)

                  https://www.lydsy.com/JudgeOnline/problem.php?id=5323

题目描述

九条可怜是一个热爱游戏的女孩子,她经常在网上和一些网友们玩一款叫做《僵尸危机》游戏。
在这款游戏中,玩家们会需要在成为僵尸之前与黑恶势力斗智斗勇,逃离被病毒感染的小岛。但是黑恶势力不会让玩家轻易得逞,他会把一些玩家抓走改造成僵尸。变成僵尸的玩家会攻击其他的玩家,被攻击的玩家会被”感染”,成为病毒的潜在宿主。
具体来说,游戏开始时,所有的玩家会获得一个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 

看了一眼题,嗯,不会,再看一眼,嗯,不错,可做,再看一眼,奥,看错了,不可做。本来以为DP题,准备放弃,后来发现是一个组合数的题,奥,那就搞一下吧。

题意:

每次给你L-R  R-L+1个编号。每次都从里面选,然后选的那个编号的所有倍数感染+本身都变成僵尸。问你这个游戏最多可以玩多少轮,就是感染的还可以选择,变成了僵尸就不能选了。计算下最少几轮可以结束比赛,数量就等于从小开始有多少个没有被感染的,就是假如2变成了僵尸4---6----8感染这样不算,计算3 5 这样没被感染的。

最大的话就是从最大的开始数量就是R-L+1  所以轮数就在sum----R-L+1这个范围内  那么就转换成了组合数学。

对于你选择的某个轮数考虑,假如是X X肯定是>=sum的   so X轮之前肯定有sum-1个基础的被感染了,就是当前是最后一个那种素数(就是在L--R之间没有比他小的而且是他的因子的数) 然后将这sum-1个数全排列下,X+1----R的也全排列下

最后ans[X]=sum*(C(n-sum,i-sum)*(i-1)!*(n-i)!)      sum代表第X位有sum种可能,C(n-sum,i-sum)表示X前边出去sum-1个数 还剩下X-1-(sum-1)个数需要从n-sum中选出来,那么剩下的不就是X后边的数了。然后将前边和后边都全排列一下就是当前X所有的贡献。将这个式子进行化简的到 ans = sum * (n-sum)! / (X-sum)! *  X!    然后题意让求的是期望轮数 *(L-R+1)!

期望轮数等于 ans[X]*X 表示当前的轮数乘以可能的情况   然后最后除以(L-R+1)!就是对于X的期望轮数 然后求个和,就可以约去(L-R+1)! 最后就是 sigma(ans[i]*i) i>=sum && i<=L-R+1 就OK了。 

(思维每天乱成Shi,每天在自闭的边缘疯狂试探)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7+5;
const long long mod= 1e9+7;
ll fac[maxn];
ll inv[maxn];
int vis[maxn];
ll Qpow(ll x,ll k)
{
    ll ans=1;
    while(k)
    {
        if(k&1)
            ans=(ans * x)%mod;
        x=(x*x)%mod;
        k=k>>1;
    }
    return ans%mod;
}
void init(int r)
{
    fac[0] = 1;
    for(int i = 1;i <= r;i++)
        fac[i] = ( fac[i-1] * i ) %mod;
    inv[r]=Qpow(fac[r],mod-2);
    for(int i=r;i>=1;i--)
        inv[i-1] = (inv[i]*i)%mod;
}
int main()
{
    int l,r;
    scanf("%d%d",&l,&r);
    init(r);
    ll ans=0;
    for(int i=l;i<=r;i++)
    {
        if(vis[i]==0)
        {
            ans++;
            for(int j=1;j*i<=r;j++)
                vis[j*i]=1;
        }
    }
    ll sum = 0;
    ll n=r-l+1;
    for(int i=ans;i<=r-l+1;i++)
        sum = (sum + (((ans * fac[n-ans])%mod * fac[i])%mod *inv[i-ans])%mod )%mod;
    printf("%lld\n",sum);
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/passer__/article/details/81428549