首先对于要求为 k k k 倍数的要求可以构造生成函数: ( 1 + x k + x 2 k + . . . + x n k ) (1+x^k+x^{2k}+...+x^{nk}) (1+xk+x2k+...+xnk)
由定理可得: ( 1 + x k + x 2 k + . . . + x n k ) = 1 1 − x k (1+x^k+x^{2k}+...+x^{nk})=\frac{1}{1-x^k} (1+xk+x2k+...+xnk)=1−xk1
对于另一种要求及 ( ∑ i = 0 k x i ) = 1 − x k + 1 1 − x (\sum_{i=0}^{k} x^i)=\frac{1-x^{k+1}}{1-x} (∑i=0kxi)=1−x1−xk+1
然后我们把这些项全部乘起来得: f ( x ) = ( 1 + x + x 1 + x 2 + . . ) 5 f(x)=(1+x+x^1+x^2+..)^5 f(x)=(1+x+x1+x2+..)5
答案就是上面这个多项式 x n x^n xn 的系数之和: A n s = ( n + 1 ) ( n + 2 ) ( n + 3 ) ( n + 4 ) 24 Ans=\frac{(n+1)(n+2)(n+3)(n+4)}{24} Ans=24(n+1)(n+2)(n+3)(n+4)
由于 n = 1 0 5 n=10^5 n=105以及优秀的模数直接用 N T T NTT NTT计算即可
#include
#define int long long
#define For(i,a,b) for ( register int i=(a);i<=(b);i++ )
#define Dow(i,b,a) for ( int i=(b);i>=(a);i-- )
#define GO(i,x) for ( int i=head[x];i;i=e[i].nex )
#define mem(x,s) memset(x,s,sizeof(x))
#define cpy(x,s) memcpy(x,s,sizeof(x))
#define YES return puts("YES"),0
#define NO return puts("NO"),0
#define GG return puts("-1"),0
#define pb push_back
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
const int N=6e5+5;
const int mo=998244353;
const int G=3;
int n,m,l1,l2,l3,l4,a[N],b[N],c[N],d[N],ans[N];
int r[N],lim=1,II=0;
char s[N];
inline int ksm(int x,int y)
{
int ret=1;
while(y)
{
if(y&1ll) ret=ret*x%mo;
x=x*x%mo;
y>>=1ll;
}
return ret%mo;
}
inline void NTT(int *a,int inv)
{
For(i,0,lim-1) if(i<r[i]) swap(a[i],a[r[i]]);
for ( register int mid=1;mid<lim;mid<<=1ll)
{
int tmp=ksm(G,(mo-1)/(mid*2ll));
if(inv) tmp=ksm(tmp,mo-2);
for ( register int i=0;i<lim;i+=mid*2ll )
{
int w=1ll;
for ( register int j=0;j<mid;j++,w=w*tmp%mo )
{
int x=a[i+j];
int y=w*a[i+j+mid]%mo;
a[i+j]=(x+y)%mo;
a[i+j+mid]=(x-y+mo)%mo;
}
}
}
if(inv)
For(i,0,lim-1) a[i]=a[i]*II%mo;
}
inline void MUL(int *f,int *g)
{
NTT(f,0),NTT(g,0);
// puts("orz");
For(i,0,lim-1) f[i]=f[i]*g[i]%mo;
NTT(f,1);
int tmp=0;
For(i,0,lim-1)
{
a[i]+=tmp;
tmp=a[i]/10ll;
a[i]%=10ll;
if(a[i]) l1=i+1;
}
}
signed main()
{
// freopen("A.in","r",stdin);
// freopen("A.out","w",stdout);
scanf("%s",s);
int len=strlen(s);
int l=0;
lim=1ll;
while(lim<=400000) lim<<=1ll,l++;
II=ksm(lim,mo-2);
For(i,0,lim-1) r[i]=r[i>>1ll]>>1ll|((i&1ll)<<(l-1));
reverse(s,s+len);
For(i,0,len-1) a[i]=s[i]-48;
int x=1;
For(i,0,len)
{
a[i]=a[i]+x;
x=a[i]/10ll;
a[i]%=10ll;
if(a[i]) l1=i+1;
}
x=1;
For(i,0,l1-1)
{
b[i]=a[i]+x;
x=b[i]/10ll;
b[i]%=10ll;
if(b[i]) l2=i+1;
}
x=1;
For(i,0,l2-1)
{
c[i]=b[i]+x;
x=c[i]/10ll;
c[i]%=10ll;
if(c[i]) l3=i+1;
}
x=1;
For(i,0,l3-1)
{
d[i]=c[i]+x;
x=d[i]/10ll;
d[i]%=10ll;
if(d[i]) l4=i+1;
}
MUL(a,b);
MUL(a,c);
MUL(a,d);
int P=0,ll=0;
Dow(i,l1-1,0)
{
P=P*10ll+a[i];
ans[i]=P/24ll;
P%=24ll;
if(ans[i]&&!ll) ll=i+1;
}
if(!ll) ll=1;
Dow(i,ll-1,0) printf("%lld",ans[i]);
return 0;
}