addimnorsux II 题解
mahaorui2012 · · 题解
本文使用 AI 进行了润色。
对
其中
左移运算对按位与运算满足分配律,所以:
每一位是独立的,因此可以拆位计算。对每一位权值
设
注意,如果
考虑生成函数。设第
站在二进制拆分的视角,没有限制时自然数的生成函数为
所以:
考虑利用平方差公式变形化简连乘式:
代回
令
则
不知道这个东西有什么很好的组合意义。
考虑如何快速计算
具体地,对
预处理组合数数组的复杂度为
::::success[std]
#include <iostream>
#include <vector>
#define int long long
#define MOD 599999
using namespace std;
const int LOGS=63;
int c[MOD][LOGS];
int inv[LOGS];
int C[LOGS],f[LOGS];
int work(int n,int T,int d){
for(int i=0;i<=n;++i){
C[i]=1;
int A=n-1+T-1ll*i*(1ll<<(d+n));
if(A<n-1) C[i]=0;
else{
C[i]=c[A%MOD][n-1];
}f[i]=(C[i]+(i?f[i-1]:0))%MOD;
}
int val=T/(1ll<<(d+n))%MOD;
vector<int> pre(n+2,1),suf(n+2,1),ifac(n+1,1);
for(int i=1;i<=n;++i) ifac[i]=1ll*ifac[i-1]*inv[i]%MOD;
for(int i=0;i<=n;++i) pre[i+1]=1ll*pre[i]*(val-i+MOD)%MOD;
for(int i=n;i>=0;--i) suf[i]=1ll*suf[i+1]*(val-i+MOD)%MOD;
int ret=0;
for(int i=0;i<=n;++i){
int cans=1ll*f[i]*pre[i]%MOD*suf[i+1]%MOD*ifac[i]%MOD*ifac[n-i]%MOD;
if((n-i)&1) cans=1ll*cans*(MOD-1)%MOD;
(ret+=cans)%=MOD;
}return ret;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
inv[1]=1;
for(int i=2;i<LOGS;++i){
inv[i]=1ll*(MOD-MOD/i)*inv[MOD%i]%MOD;
}
c[0][0]=1;
for(int i=1;i<MOD;++i){
c[i][0]=1;
for(int j=1;j<LOGS;++j){
c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
}
}
int q;
cin>>q;
while(q--){
int n,S;
cin>>n>>S;
if(n>=60 || S<(1ll<<n)-1){
cout<<"0\n";
continue;
}
int ans=0;
S-=(1ll<<n)-1;
for(int d=0;S>=0;S-=(1ll<<d)*((1ll<<n)-1),++d){
int k=d+n;
int w=(1ll<<k)%MOD;
int cans=(work(n,S,d)-work(n,S-(1ll<<d),d)+MOD)%MOD;
(ans+=1ll*cans*w%MOD)%=MOD;
}cout<<ans<<'\n';
}
return 0;
}