题面:
题解:
具体见代码注释。
需要注意的是,sort 的 cmp 就算是参数是引用类型,在cmp 中交换两个数也会出问题。
cmp中二分找第一不相同的字母的位置。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=998244353;
const double eps=0.1;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=100100;
const int maxm=100100;
const int up=100000;
ll p10[maxn],ans[maxn];
llu h[maxn],p[maxn];
int pos[maxn],n;
char str[maxn];
//a是b的前缀
//a-->x,b-->x+y
//ab-->x+x+y,ba-->x+y+x
//若a在前面则 ab>ba
//x+y>y+x
bool check(const int a,const int b)
{
int l=1,r=b;
int pos=0,mid;
int leny=b-a;
llu hy=h[b]-h[a]*p[b-a];
while(l<=r)
{
mid=(l+r)>>1;
if(mid<=leny)
{
if(h[mid]==h[a+mid]-h[a]*p[mid]) l=mid+1;
else pos=mid,r=mid-1;
}
else
{
if(h[mid]==hy*p[mid-leny]+h[mid-leny]) l=mid+1;
else pos=mid,r=mid-1;
}
}
if(pos==0) return true;
if(pos<=leny) return str[pos]>=str[a+pos];
else return str[pos]>=str[pos-leny];
}
bool cmp(const int &a,const int &b)
{
if(a<b) return check(a,b);
else return !check(b,a);
}
int main(void)
{
scanf("%s",str+1);
n=strlen(str+1);
p[0]=p10[0]=1;
for(int i=1;i<=n;i++)
{
p[i]=p[i-1]*hp;
h[i]=h[i-1]*hp+str[i];
p10[i]=p10[i-1]*10%mod;
ans[i]=(ans[i-1]*10+str[i]-'0')%mod;
pos[i]=i;
}
sort(pos+1,pos+n+1,cmp);
ll res=0;
for(int i=1;i<=n;i++)
res=(res*p10[pos[i]]+ans[pos[i]])%mod;
printf("%lld\n",res);
return 0;
}