A

B

C

容斥原理。

定义一个函数 cal(x) 来 计算 1 ~ x 中 是 2 3 5 7 倍数 的总个数,最后输出 r - cal(r) - (l - 1 - cal(l - 1)) 即可。

可以直接枚举 但是这里讲一下二进制枚举的写法。

auto cal = [&](int n) -> int
{
	vector<int> v = {2, 3, 5, 7};
	int ans = 0;
	// 我们最后要计算 2 + 3 + 5 + 7 - (2 * 3 + 2 * 5 + ...)
	// 所以 奇数加 偶数减
 
	for (int mask = 1; mask < (1ll << v.size()); mask++)
	{
		// 譬如mask的二进制是1011 那么即为选择了2 3 7
		int cur = 1, tot = 0; // cur 表示 选择的数字 tot表示个数
		for (int i = 0; i < v.size(); i++)
		{
			if ((mask >> i) & 1)
			{
				/* 接下来 cur *= v[i] 的操作 有可能会 爆 long long
				所以我们提前判断 如果 cur * v[i] > n
				也就是 cur > n / v[i] 时 我们就直接令cur = n + 1 然后break
				*/
				if (cur > n / v[i])
				{
					cur = n + 1;
					break;
				}
				cur *= v[i];
				tot++;
			}
		}
 
 
		if (tot & 1) // 选择的数字数量是奇数 根据容斥原理 我们应该加上
		{
			ans += n / cur;
		}
		else ans -= n / cur;
	}
 
	// 这里直接return n - ans 省得麻烦
	return n - ans;
};

根据这个代码 最后我们计算 即可。

可以做一下 [牛客的题目集]((1条未读私信) 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ) 加深理解

D

概率怎么算?

比方说有n条线段 选择每一条线段的概率分别是 p[i]

那么我们4条线段 选择2和4 的总概率就是 P = (1 - p[1]) * p[2] * (1 - p[3]) * p[4]

我们钦定一个初始概率 最后要求的概率是上面P 那么每一个概率就要乘上一个系数:

又有 化简即可。

总之 记 ,下一步就是如何表示从1到m的覆盖了。

表示 在变换后的概率空间中,通过激活某些线段,使得位置1到i-1都被恰好覆盖,且在位置i”停下”的概率

我们有 作为初始化,接下来 对于每一段 组合,都应该有:

其中 表示 安稳到达 l - 1 的概率,w表示后面这一段存在的概率,二者相乘是因为遵循分步乘法计数原理; 加上后面这一段 是因为遵循分类加法计数原理。

最后我们就求得了 作为 从0开始 安稳到达 m 的概率 最后跟 相乘 取模 即可。

// 快速幂
int power(int base, int exp)
{
    int res = 1;
    base %= MOD;
    while (exp > 0)
    {
        if (exp & 1)
            res = (res * base) % MOD;
        base = (base * base) % MOD;
        exp >>= 1;
    }
    return res;
}
 
// 模逆元
int inv(int x)
{
    return power(x, MOD - 2);
}
 
struct datas
{
    int l, r;
    int w; // 存储权重
};
 
void solve()
{
    int n, m;
    cin >> n >> m;
 
    int p0 = 1;
 
    vector<datas> v(n);
    for (int i = 0; i < n; i++)
    {
        int l, r, p, q;
        cin >> l >> r >> p >> q;
        auto curp = p * inv(q) % MOD;
        // p0 *= (1 - curp); 是错的 要特别注意取模
        p0 = (p0 % MOD * (1 + MOD - curp) % MOD) % MOD;
        v[i] = {l, r, curp * inv((1 + MOD - curp) % MOD) % MOD};
    }
 
    map<int, vector<pair<int, int>>> mp;
 
    for (auto [l, r, w] : v)
    {
        mp[l].emplace_back(r, w);
    }
 
    vector<int> dp(m + 1, 0);
    dp[0] = 1;
 
    for (int l = 1; l <= m; l++)
    {
        for (auto [r, w] : mp[l])
        {
            dp[r] = (dp[r] + dp[l - 1] * w) % MOD;
        }
    }
 
    cout << p0 * dp[m] % MOD;
}

上面出现了很多 %MOD 要是图省事可以找哥哥的[Z模板](jiangly算法模板收集 - hh2048 - 博客园) 那样会方便的多。