AtCoder Regular Contest 116 D - I Wanna Win The Game

本文介绍了使用动态规划解决AtCoder ARC116 D题的解决方案,通过计算背包中2的幂次方的组合方式来填充背包,优化背包容量为m时异或和为0的物品选择方案,时间复杂度为O((n+m)log^2m)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://atcoder.jp/contests/arc116/tasks/arc116_d

dp[k][i]表示当前已经枚举到2^k了,然后背包容量是i的时候方案数是多少

每次枚举当前2^k放多少个去填,因为要是异或=0,所以必须偶数个,然后方案数就是n个里面选t个位置放下这些2^k,就是C(n,t)

k=logm  i=m t=m/2^k ,所以复杂度是O((n+m)log^2m) ,感觉n,m=2e4也能过啊

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=1e5+10;
const int mod=998244353;

int n,m;
ll fac[maxl],inv[maxl];
ll dp[21][maxl];

inline ll qp(ll a,ll b)
{
	ll ans=1,cnt=a;
	while(b)
	{
		if(b&1) ans=ans*cnt%mod;
		cnt=cnt*cnt%mod;
		b>>=1;
	}
	return ans;
}
inline ll c(int n,int r)
{
	if(r>n || r<0) return 0;
	return fac[n]*inv[n-r]%mod*inv[r]%mod;
}
inline void add(ll &a,ll b)
{
	a=(a+b)%mod;
}

int main()
{
	scanf("%d%d",&n,&m);
	fac[0]=1;
	for(int i=1;i<maxl;i++)
		fac[i]=fac[i-1]*i%mod;
	inv[maxl-1]=qp(fac[maxl-1],mod-2);
	for(int i=maxl-2;i>=0;i--)
		inv[i]=inv[i+1]*(i+1)%mod;
	for(int i=0;i<=min(n,m);i+=2)
		dp[0][i]=c(n,i);
	for(int k=1;k<=20;k++)
		for(int i=0;i<=m;i++)
			for(int t=0;t<=n;t+=2)
			{
				if(t*(1<<k)+i>m)
					break;
				add(dp[k][t*(1<<k)+i],dp[k-1][i]*c(n,t));
			}
	printf("%lld",dp[20][m]);
	return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值