题解:P14565 翻转
i_love_xqh · · 题解
不妨设
考虑从两边往中间填,先枚举倍数。如果填了
如果直接枚举状态和第
然后需要分讨长度为奇偶的情况,以及当长度恰好为
一个卡常小技巧是对于一个进制,有一些倍数一定不存在,可以打表出来不枚举即可。当然也可以写记忆化搜索。
附一份未经卡常的代码。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int p=998244353;
char s[N];
int pos[N];
int f[N>>1][16][16][2][2],g[N>>1][16][16];
void chmod(int &x,int y){x+=y;if(x>=p)x-=p;}
int main(){
int k;scanf("%d",&k);
scanf("%s",s+1);int n=strlen(s+1);
for(int i=1;i<=n;i++)pos[i]=(s[i]>='0'&&s[i]<='9'?s[i]-'0':s[i]-'A'+10);
int l=(n-1)/2,ans=0;//<n
for(int x=1;x<k;x++){
for(int i=0;i<=l;i++)for(int j1=0;j1<k;j1++)for(int j2=0;j2<k;j2++)g[i][j1][j2]=0;
g[0][0][0]=1;
for(int i=1;i<=l;i++){
for(int a=0;a<k;a++){
for(int j1=0;j1<k;j1++){
int b=(a*x+j1)%k,k1=(a*x+j1)/k,k2;
if(i==1&&!b)continue;
int c=b*x%k,j2=b*x/k;
if(c<=a)k2=a-c;else j2++,k2=k-c+a;
int &v=g[i-1][j1][j2];
if(!v)continue;
chmod(g[i][k1][k2],v);
}
}
}
for(int i=1;i<=l;i++){
for(int j=0;j<k;j++){
if(!g[i][j][j])continue;
chmod(ans,g[i][j][j]);
}
}
for(int i=0;i<=(n&1?l-1:l);i++){
for(int j1=0;j1<k;j1++){
for(int a=(i==0);a<k;a++){
int b=(a*x+j1)%k;if(b!=a)continue;
int j2=(a*x+j1)/k;if(!g[i][j1][j2])continue;
chmod(ans,g[i][j1][j2]);
}
}
}
}
l=n/2;//=n
for(int x=1;x<k;x++){
for(int i=0;i<=l;i++)for(int j1=0;j1<k;j1++)for(int j2=0;j2<k;j2++)for(int l1=0;l1<2;l1++)for(int l2=0;l2<2;l2++)f[i][j1][j2][l1][l2]=0;
f[0][0][0][1][0]=1;
for(int i=1;i<=l;i++){
for(int l1=0;l1<2;l1++){
for(int l2=0;l2<2;l2++){
for(int a=0;a<k;a++){
for(int j1=0;j1<k;j1++){
int b=(a*x+j1)%k,k1=(a*x+j1)/k,k2;
if(i==1&&!b)continue;
if(l1&&b>pos[i])continue;
int c=b*x%k,j2=b*x/k;
if(c<=a)k2=a-c;else j2++,k2=k-c+a;
int &v=f[i-1][j1][j2][l1][l2];
if(!v)continue;
int L1=l1&&b==pos[i],L2=a==pos[n-i+1]?l2:(a>pos[n-i+1]);
chmod(f[i][k1][k2][L1][L2],v);
}
}
}
}
}
if(n&1){
for(int j1=0;j1<k;j1++){
for(int a=(n==1);a<k;a++){
int b=(a*x+j1)%k;if(b!=a)continue;
int j2=(a*x+j1)/k;
for(int l1=0;l1<2;l1++){
for(int l2=0;l2<2;l2++){
int &v=f[l][j1][j2][l1][l2];
if(!v)continue;
if(l1&&(a>pos[l+1]||(a==pos[l+1]&&l2)))continue;
chmod(ans,v);
}
}
}
}
}
else{
for(int j=0;j<k;j++){
for(int l1=0;l1<2;l1++){
for(int l2=0;l2<2;l2++){
int &v=f[l][j][j][l1][l2];
if(!v)continue;
if(l1&&l2)continue;
chmod(ans,v);
}
}
}
}
}
printf("%d",ans);
return 0;
}