题解:洛谷P10128 「Daily OI Round 3」Xor Graph

题目链接:洛谷P10128 「Daily OI Round 3」Xor Graph

首先,观察到如果 xxory=2k,k[1,n),那么 xy 的二进制位上有且仅有一位不同。

其次,还要保证 x>y,那么只有当 y 是将 x 的某二进制位 1 变为 0 时,才可以使两个性质都成立。

考虑求 i=12nj=1,ji2nf(i,j),如果枚举点对,那么复杂度一定超,于是我们枚举每种长度的线段的个数,动态考虑该问题,每走一步,就将二进制位上的某个 1 变为 0,直到二进制位上只有一个 1 为止。

就可以发现,从一个数出发存在长度为 n 的路径,当且仅当这个数二进制位上 1 的个数大于 n

现在有 2n 个点,因此每个数都可以表示成一个 n 位二进制数,可以先枚举这个数的二进制位上有多少个 1,再钦定哪几个位上是 1,最后确定删几个 1 以及删 1 的顺序。

现在,答案就变成了求 i=2n(ni)j=1i1ij

无脑大力推式子:原式

=i=2nj=1i1(ni)ij=i=2nj=1i1(ni)(ij)j!=i=2nj=1i1(nj)(njij)j!=j=1n1i=j+1n(nj)(njij)j!=j=1n1(nj)j!i=j+1n(njij)=j=1n1(nj)j!(2nj1)

已经 O(n) 不能再优化了,但这道题的数据十分可爱极限,导致我们只能递推预处理qwq。

将括号拆开,得:j=1n1(nj)j!2njj=1n1(nj)j!

现在两边都可以预处理,那这道题就做完了。

代码(其实不长):

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e7 + 9, mod = 998244353;
int ans1[N], ans2[N], mi;
int t;
signed main(){
	ans1[1] = ans2[1] = 0;
	ans1[2] = 2, ans2[2] = 4;
	mi = 4;
	for(int i = 3; i <= 1e7; i++){
		ans1[i] = (ans1[i - 1] * i + i) % mod;//减号左边递推 
		ans2[i] = (ans2[i - 1] * i + i * mi) % mod;//减号右边递推 
		mi = mi * 2 % mod;
	}
	scanf("%d",&t);
	while(t--){
		int x;
		scanf("%d",&x);
		printf("%lld\n",(ans2[x] - ans1[x] + mod) % mod);
	}
	return 0;
} 
posted @   JPGOJCZX  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示