题意:定义函数f(x,y):
要计算
分析:枚举是n²的复杂度,所以肯定和easy版本一样可以找到规律。
我们随便拿两个数来模拟一下,比如123 、 45 ,考虑
f(123,45) + f(45,123)
= 12435 + 14253
1在10^(5-1)位作了两次贡献,
2、4在10^(4-1) 10 ^(3-1)位分别作了一次贡献,
1、5在10^(2-1) 10 ^(1-1)位分别作了一次贡献,
所以规律就是:对于两个长度分别为len1,len2的数(len1>=len2),len1中超出的部分数作两次同样的贡献,其余部分以及len2的每一位都作2次不一样的贡献。
我们需要记录位数为i的的数的个数,然后对于每个a[i]
,枚举位数为j的数的个数,再对a[i]
的每一位算出贡献即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 1e5+10;
const int mx = 40;
const int mod = 998244353;
const ll inf = 34359738370;
const int INF = 1e9+7;
int n;
ll a[maxn];
int num[15];//长度为i的数的个数
ll ten[32];
void getnum(ll x)
{
int cnt=0;
while(x)
{
cnt++;
x/=10;
}
num[cnt]++;
}
ll solve(ll x,ll len)//x 和所有长度为len的数 进行运算 求出x的贡献 枚举x的每一位
{
int index=0;
ll ret=0;
while(x)
{
index++;
int d=x%10;
x/=10;
if(index>len)
{
ret=(ret+2*num[len]*d%mod*ten[index-1+len])%mod;
}
else
{
ret=(ret+num[len]*d%mod*ten[2*index-1])%mod;
ret=(ret+num[len]*d%mod*ten[2*index-2])%mod;
}
}
return ret;
}
int main()
{
ten[0]=1;
for(int i=1;i<=30;i++) ten[i]=(ten[i-1]*10)%mod;
int t;t=1;
while(t--)
{
scanf("%d",&n);
ll ans=0;
for(int i=1;i<=n;i++)
{
scanf("%I64d",a+i);
getnum(a[i]);
}
for(int i=1;i<=n;i++)
{
ll b=a[i];
for(int j=1;j<=10;j++)
{
ans=(ans+solve(b,j))%mod;
}
}
cout<<ans<<'\n';
}
return 0;
}