時間限制: 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
*************************/