列表

详情


NC253623. Kevin逛超市

描述

氧气少年在逛超市。

他总共买了 n 件物品,当他走到超市出口时,出口的报警器响了起来。

已知恰好有一件物品使报警器报警,并且这件使报警器报警的物品于 n 件物品中随机分布。现在氧气少年想找出这件使报警器报警的物品,他采取这样的方式找出这件物品:

将这 n 件物品标号为 1\dots n

定义集合 S 中最小的元素为 S_{\min}S 中最大的元素为 S_{\max}S 包含的元素数量为 |S|

氧气少年先将所有物品的编号放入集合 A,即令集合 A=\lbrace 1,2,\cdots n \rbrace。然后他会进行下面的操作:

  1.  令集合 B=\lbrace A_{\min},A_{\min}+1\cdots \lfloor \frac{A_{\min}+A_{\max}}{2} \rfloor\rbrace,然后执行步骤 2;
  2.  将集合 B 中对应编号的物品通过报警器。

氧气少年想知道,从他开始查找物品开始,到他找到这件物品为止,氧气少年将物品通过报警器的次数(即:步骤 2 执行次数)的期望。

可以证明,答案可以表示成 \frac{p}{q} 的形式。其中,p\geq 0,q\geq 1,\gcd(p,q)=1,q\mod 998244353\neq 0。因此你只需输出 p\cdot q^{998244351}\mod 998244353 即可。

输入描述

第一行包含一个整数 T(1\leq T\leq 2\cdot 10^5),表示测试用例的组数。

对于每组测试用例:

仅输入一行,包含一个整数 n(1\leq n\leq 10^9),表示物品的数量。保证 n\mod 998244353\neq 0

输出描述

对于每组测试用例:

仅输出一行,包含一个整数,表示答案。

示例1

输入:

3
1
2
3

输出:

1
499122178
332748120

说明:

对于第一组测试用例:

如果 1 号物品是让报警器报警的物品,那么次数为 1,概率为 \frac{1}{1}。期望为 11\cdot 1^{998244351} \mod 998244353=1

对于第二组测试用例:

如果 1 号物品是让报警器报警的物品,那么次数为 1,概率为 \frac{1}{2};如果 2 号物品是让报警器报警的物品,那么次数为 2,概率为 \frac{1}{2}。期望为 \frac{1}{2}\cdot 1+\frac{1}{2}\cdot 2=\frac{3}{2}3\cdot 2^{998244351} \mod 998244353=499122178

对于第三组测试用例:

如果 1 号物品是让报警器报警的物品,那么次数为 2,概率为 \frac{1}{3};如果 2 号物品是让报警器报警的物品,那么次数为 3,概率为 \frac{1}{3};如果 3 号物品是让报警器报警的物品,那么次数为 2,概率为 \frac{1}{3}。期望为 \frac{1}{3}\cdot 2+\frac{1}{3}\cdot 3+\frac{1}{3}\cdot 2=\frac{7}{3}7\cdot 3^{998244351} \mod 998244353=332748120

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 895ms, 内存消耗: 106796K, 提交时间: 2023-07-14 22:11:43

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e6+5;
const int mod = 998244353;
unordered_map<int,int>mp;
int qpow(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=res*a%mod;
		a=a*a%mod;
		b>>=1; 
	}
	return res;
}
int dfs(int n){
	if(mp.count(n)) return mp[n];
    int m=(1+n)>>1;
	return mp[n]=(dfs(m)+dfs(n-m)+n)%mod;
}
signed main(void){
	ios::sync_with_stdio(false);cin.tie(0);
    mp[1]=1;
    mp[2]=3;
	int T=1;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		cout<<dfs(n)*qpow(n,mod-2)%mod<<"\n"; 
	}		
	return 0;
}

pypy3 解法, 执行用时: 1842ms, 内存消耗: 193556K, 提交时间: 2023-07-14 22:54:57

from functools import lru_cache
from sys import stdin

input = stdin.readline

mod = 998244353


@lru_cache(None)
def f(n: int):
    res = n
    if n == 1:
        return 1
    if res >= mod:
        res -= mod
    m = (n + 1) // 2
    if m > 1:
        res += f(m)
        if res >= mod:
            res -= mod
    res += f(n - m)
    if res >= mod:
        res -= mod
    return res


for _ in range(int(input())):
    n = int(input())
    print(f(n) * pow(n, mod - 2, mod) % mod)

Python3 解法, 执行用时: 3870ms, 内存消耗: 241736K, 提交时间: 2023-07-20 20:59:30

from functools import cache
from sys import stdin
input = stdin.readline
mod=998244353
@cache
def dp(n:int):
    time=n
    if n==1:return 1
    if time>=mod:time-=mod
    m=(1+n)//2
    if m>1:
        time+=dp(m)
        if time>=mod: time-=mod
    time+=dp(n-m)
    if time >= mod: time -= mod
    return time
for  _ in range(int(input())):
    k=int(input())
    print(dp(k)*pow(k,mod-2,mod)%mod)

上一题