T666848 闪现树 题解
出的很好的计数题。
我们的最初想法是,发现只会向下延伸
那么
发现当
考察这些“不能延伸”的节点的性质,发现:
对于一个往下延伸
然后每一层节点个数就是
#include<bits/stdc++.h>
#define _for(i,x,y) for(int i=x;i<=y;++i)
#define _forp(i,x,y,z) for(int i=x;i<=y;i+=z)
#define _rep(i,x,y) for(int i=x;i<y;++i)
using namespace std;
const int N=10000005,mod=998244353;
int ans=0,f[N],fac[N],inv[N],pow4[N],g[N],n,l,r;
int qpow(int x,int y){
if(y<0) return 0;
int ans=1;
x%=mod;
while(y){
if(y&1) ans=1ll*ans*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return ans;
}
int C(int n,int m){
if(n==m) return 1;
if(m==0) return 1;
if(n<m) return 0;
if(m<0) return 0;
return 1ll*fac[n]*inv[n-m]%mod*inv[m]%mod;
}
void build(){
fac[0]=pow4[0]=1;
_for(i,1,N-5) fac[i]=1ll*fac[i-1]*i%mod,pow4[i]=1ll*pow4[i-1]*4ll%mod;;
inv[N-5]=qpow(fac[N-5],mod-2);
for(int i=N-6;i;--i) inv[i]=1ll*inv[i+1]*(i+1ll)%mod ;
}
void solve(){
cin>>n>>l>>r;
build();
f[0]=1;
g[0]=0;
_for(i,1,min(N-5,2*n)){
g[i]=f[i-1]*2%mod;
f[i]=(g[i-1]*2%mod+f[i-1])%mod;
if(l<=i&&i<=r){
ans^=(f[i]+g[i])%mod;
}
if(i>=n) f[i]-=(1ll*pow4[i-n]*C(n,i-n))%mod,f[i]+=mod,f[i]%=mod;
}
cout<<ans<<'\n';
}
signed main(){
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
int T=1;
// cin>>T;
while(T--){
solve();
}
return 0;
}