結果
| 問題 | No.3399 One Two Three Two Three |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-01-10 21:53:49 |
| 言語 | C++17 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 4,498 bytes |
| 記録 | |
| コンパイル時間 | 2,808 ms |
| コンパイル使用メモリ | 240,312 KB |
| 実行使用メモリ | 114,856 KB |
| 最終ジャッジ日時 | 2026-01-10 21:54:35 |
| 合計ジャッジ時間 | 43,505 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 35 TLE * 2 -- * 3 |
ソースコード
#include<bits/stdc++.h>
#define int long long
#define poly basic_string<node>
using namespace std;
const int N=65,M=1e5+5,Mod=998244353,INV2=499122177;
int n,p1,p2,p3,p4,p5,pw2[N],pw3[N],g,invg;
struct node{
int x,y;
}w2,w3,ans,a[M],b[M],c[M];
poly P[N][N],Q[N][N],R[N][N],S[N],T[N],F[N],G[N],H[N],W0[N],W1[N],now={{1,0}};
node operator+(node a,node b)
{
a.x=(a.x+b.x)%Mod,a.y=(a.y+b.y)%Mod;
return a;
}
node operator-(node a,node b)
{
a.x=(a.x-b.x+Mod)%Mod,a.y=(a.y-b.y+Mod)%Mod;
return a;
}
void operator-=(node &a,node b)
{
a.x=(a.x-b.x+Mod)%Mod,a.y=(a.y-b.y+Mod)%Mod;
}
void operator+=(node &a,node b)
{
a.x=(a.x+b.x)%Mod,a.y=(a.y+b.y)%Mod;
}
node operator*(node a,node b)
{
return {(a.x*b.x-3*a.y*b.y%Mod+3*Mod)%Mod,(a.x*b.y+a.y*b.x)%Mod};
}
node operator*(node a,int b)
{
return {a.x*b%Mod,a.y*b%Mod};
}
int ksm(int x,int y)
{
int ret=1,bace=x;
while(y)
{
if(y&1)ret=ret*bace%Mod;
bace=bace*bace%Mod;
y>>=1;
}
return ret;
}
node ksm(node x,int y)
{
node ret={1,0},bace=x;
while(y)
{
if(y&1)ret=ret*bace;
bace=bace*bace;
y>>=1;
}
return ret;
}
node inv(node a)
{
int val=ksm((a.x*a.x+3*a.y*a.y)%Mod,Mod-2);
return {a.x*val%Mod,Mod-a.y*val%Mod};
}
node operator/(node a,node b)
{
return a*inv(b);
}
namespace NTT
{
node A[M],B[M];
int tr[M];
int init(int n)
{
int ret=1;
while(ret<n)ret<<=1;
for(int i=0;i<ret;i++)tr[i]=(tr[i>>1]>>1)|((i&1)?(ret>>1):0);
return ret;
}
void ntt(node *f,int n,int op)
{
for(int i=0;i<n;i++)if(i<tr[i])swap(f[i],f[tr[i]]);
for(int len=1;len<n;len<<=1)
{
int tmp=(op==1)?g:invg;
tmp=ksm(tmp,(Mod-1)/(len<<1));
for(int i=0;i<n;i+=(len<<1))
{
int now=1;
for(int j=0;j<len;j++)
{
if(f[i+j+len].x)f[i+j+len].x%=Mod;
if(f[i+j+len].y)f[i+j+len].y%=Mod;
node x=f[i+j+len]*now;
f[i+j+len]={f[i+j].x-x.x+Mod,f[i+j].y-x.y+Mod},f[i+j].x+=x.x,f[i+j].y+=x.y,now=now*tmp%Mod;
}
}
}
for(int i=0;i<n;i++)
{
if(f[i].x)f[i].x%=Mod;
if(f[i].y)f[i].y%=Mod;
}
if(op==-1)
{
int inv=ksm(n,Mod-2);
for(int i=0;i<n;i++)f[i]=f[i]*inv;
}
}
void solve(int n,int m,node *f,node *g,node *s)
{
int k=init(n+m);
for(int i=0;i<n;i++)A[i]=f[i];
for(int i=0;i<m;i++)B[i]=g[i];
for(int i=n;i<k;i++)A[i]={0,0};
for(int i=m;i<k;i++)B[i]={0,0};
ntt(A,k,1),ntt(B,k,1);
for(int i=0;i<k;i++)s[i]=A[i]*B[i];
ntt(s,k,-1);
}
}
poly operator*(poly f,poly g)
{
if(!f.size()||!g.size())return {{0,0}};
poly h;
if(f.size()<30||g.size()<30)
{
h.resize(f.size()+g.size()-1);
for(int i=0;i<f.size();i++)for(int j=0;j<g.size();j++)h[i+j]+=f[i]*g[j];
return h;
}
for(int i=0;i<f.size();i++)a[i]=f[i];
for(int i=0;i<g.size();i++)b[i]=g[i];
NTT::solve(f.size(),g.size(),a,b,c);
for(int i=0;i<f.size()+g.size()-1;i++)h+=c[i];
return h;
}
poly operator+(poly f,poly g)
{
if(f.size()<g.size())swap(f,g);
for(int i=0;i<g.size();i++)f[i]+=g[i];
return f;
}
poly calc0(poly f,node x)
{
node now={1,0};
for(int i=0;i<f.size();i++)f[i]=now*f[i],now=now*x;
return f;
}
poly calc1(poly f,int k,int b)
{
poly g;
for(int i=b;i<f.size();i+=k)g+=f[i];
return g;
}
poly s;
signed main()
{
w2={Mod-1,0},w3={Mod-INV2,INV2},g=3,invg=ksm(g,Mod-2);
scanf("%lld",&n);
p1=p2=p3=p4=p5=1;
s+={1,0};
if(p1)s+={Mod-1,0};
if(p2)s+={Mod-1,0};
if(p3)s+={Mod-1,0};
Q[0][0]=s,F[0]=G[0]=S[0]=P[0][0]={{1,0}},pw2[0]=pw3[0]=1;
for(int i=0;i<=60;i++)S[i]={{1,0}};
for(int i=1;i<=60;i++)pw2[i]=2*pw2[i-1],pw3[i]=3*pw3[i-1];
for(int i=0;i<=60;i++)
for(int j=0;j<=60;j++)
{
Q[i+1][j]=calc1(Q[i][j]*calc0(Q[i][j],w2),2,0);
Q[i][j+1]=calc1(Q[i][j]*calc0(Q[i][j],w3)*calc0(Q[i][j],w3*w3),3,0);
S[i+j]=S[i+j]*Q[i][j];
}
for(int i=0;i<=60;i++)T[i]=S[i];
H[0]=s;
for(int i=1;i<=60;i++)S[i]=S[i]*S[i-1],F[i]=F[i-1]*Q[0][i],G[i]=G[i-1]*Q[i][0],H[i]=H[i-1]*Q[0][i];
for(int i=0;i<=60;i++)W0[i]=calc0(S[i],w2),W1[i]=calc0(S[i],w3)*calc0(S[i],w3*w3);
for(int i=0;i<=60;i++)
for(int j=0;j<=38&&i+j<=60;j++)
{
int tmp=n/pw2[i]/pw3[j];
if(!tmp)
{
if(R[i][j].size())ans+=R[i][j][0]/S[i+j][0];
continue;
}
poly ww=P[i][j]*W0[i+j];
if(p4)P[i+1][j]=P[i+1][j]+calc1(ww,2,tmp&1)*F[i+j+1];
if(p5)P[i][j+1]=P[i][j+1]+calc1(P[i][j]*W1[i+j],3,tmp%3)*G[i+j+1];
R[i+1][j]=R[i+1][j]+calc1(R[i][j]*W0[i+j]+(poly){{0,0},{1,0}}*ww,2,tmp&1)*H[i+j+1];
}
printf("%lld",ans.x);
return 0;
}