D. 抗疫斗争

8 篇文章 0 订阅
5 篇文章 0 订阅
题目描述

新冠疫情爆发以来,病毒不断地扩散传播,而人类也在不断采取各种措施遏制病毒传播。于是我们可以为这场抗疫斗争建立一个数学模型,将病毒的不断传播和人类的不断采取措施抽象为一场双方轮流行动的博弈。我们认为人类与病毒的每轮行动都可以选择一个正整数作为行动值来评估。然而,出于各方面限制,双方的所有行动值总和
必须等于一个数m,且每次的行动值不能超过对方上轮的行动值。对人类来说,要遏制疫情,就应成为最后行动的一方,也就是说,在本方的某次行动后,行动值总和m恰好被消耗完。
假设人类先行动,那么我们只需一鼓作气消耗完所有m点行动值,就能战胜病毒。然而在最开始的阶段出于认识不到疫情的严重性,往往最难开展大规模行动。出于这个原因,我们令hm表示在行动值总和为m的情况下,人类(即先行动方)的第一次行动最少要多少行动值,才能保证自己必胜。
出于统计需要,某科学家记f[i]=∑m|i hm,并想知道 。方便起见,对998244353取模。你能帮个忙吗?

输入格式

第一行输入一个数 。

输出格式

一行一个数,表示答案。

样例输入
3
样例输出
6

限制及约定
本题采用子任务形式评测。

子任务编号n<=分值
131
210009
310^531
410^1128
55*10^1326
610^155

对于所有数据,满足1<=n<=10^15。

思路

首先考虑如何计算hm
如果m为奇数,那么显然hm=1(你一个我一个,先手胜)
如果m为偶数,那么我们可以选一个数k,使得(m/k)%2==1,显然k最小为lowbit(m)
所以hm=lowbit(m)
下面我们来考虑计算f(n)的前缀和,则
在这里插入图片描述
们考虑枚举hi的取值,并统一计算其贡献。方便起见,我们记
复杂度O(sqrt(n))
在这里插入图片描述
在这里插入图片描述

代码
#include<bits/stdc++.h>
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int mod=998244353,N=1e6+77;
void inc(int &x,int y) 
{
	x=x+y>=mod?x+y-mod:x+y;
}
long long n;
int ans,val[N];
int work(long long x)
{
	long long ans=0;
	int sq=sqrt(x);
	for(int i=1;i<=sq;i++)ans+=(x/i);
	ans=(2*ans-1ll*sq*sq)%mod;
	return ans;
}
int main()
{
	scanf("%lld",&n);
	for(long long a=1;a<=n;a<<=1)
		inc(ans,1ll*(a-(a>>1))%mod*work(n/a)%mod);
	printf("%d",ans);
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值