题解:P10707 永恒(Eternity)
切的最快的一个,感觉比
题目看起来就很线性基。我们先统计有多少种典型基能凑出
具体来说,假设
现在我们已经确定了典型基,还要做的就是根据典型基确定原序列。假设典型基的大小为
现在问题就是求出大小为
Code:
#include<bits/stdc++.h>
#define ll long long
#define pn putchar('\n')
#define mclear(a) memset(a,0,sizeof a)
#define fls() fflush(stdout)
#define maxn 100005
#define int ll
#define mod 998244353
using namespace std;
int re()
{
int x=0;
bool t=1;
char ch=getchar();
while(ch>'9'||ch<'0')
t=ch=='-'?0:t,ch=getchar();
while(ch>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return t?x:-x;
}
int n,m,ans;
int f[70][70],g[70],h[70][70],mi[70];
int ksm(int x,int y)
{
int ret=1;
while(y)
{
if(y&1)ret=ret*x%mod;
x=x*x%mod,y>>=1;
}
return ret;
}
namespace ZH
{
int jc[maxn],inv[maxn];
void zh_init()
{
jc[0]=1;
for(int i=1;i<=n;i++)
jc[i]=jc[i-1]*i%mod;
inv[n]=ksm(jc[n],mod-2);
for(int i=n;i;i--)
inv[i-1]=inv[i]*i%mod;
}
int A(int x,int y)
{
if(x<y)return 0;
return jc[x]*inv[x-y]%mod;
}
int C(int x,int y)
{
return A(x,y)*inv[y]%mod;
}
}
using namespace ZH;
int fu(int x)
{
return x&1?-1:1;
}
signed main()
{
n=re(),m=re();
zh_init();
mi[0]=1;
for(int i=1;i<=60;i++)
mi[i]=mi[i-1]*2%mod;
f[60][0]=1;
for(int i=59;~i;i--)
{
if(m>>i&1)
{
for(int j=1;j<=60;j++)
f[i][j]=(f[i+1][j-1]+mi[j-1]*f[i+1][j])%mod;
}
else
{
f[i][0]=f[i+1][0];
for(int j=1;j<=60;j++)
f[i][j]=mi[j-1]*f[i+1][j]%mod;
}
}
for(int i=0;i<=60;i++)
{
int x=1;
for(int j=1;j<=n;j++)
x=(mi[i]+n-j)%mod*x%mod;
g[i]=x*inv[n]%mod;
}
h[0][0]=1;
for(int i=1;i<=60;i++)
{
h[i][0]=1;
for(int j=1;j<=i;j++)
h[i][j]=(h[i-1][j-1]+mi[j]*h[i-1][j])%mod;
}
for(int i=0;i<=60;i++)
{
for(int j=1;j<=i;j++)
(g[i]-=h[i][j]*g[i-j])%=mod;
(ans+=g[i]*f[0][i])%=mod;
}
if(ans<0)
ans+=mod;
printf("%lld",ans);
return 0;
}