比赛的时候没看到模数,用java大数在写,最后看到的时候已经慌了。。
把贡献算清楚就可以
下面是贡献的推导
有五位数 abcde * 10个
有两位数 fg * 3 个
那么这两种数组成的情况就是 abcdfeg 或 abcfdge,现在只考虑五位数在前,两位数在后的情况,
五位数的情况是abcd_e_,每个五位数出现了3次,那直接把10个五位数在每位上求和,然后这个五位数的贡献*3,
两位数的情况是____f_g,每个两位数出现了10次,那么也直接把3个两位数在每位上求和,然后这个两位数的贡献*10
#include<bits/stdc++.h> using namespace std; #define maxn 100005 #define ll long long #define mod 998244353 ll n,a[maxn],A[22]; ll cnt[11],x[11][11]; void calc(ll a){ ll len=0,tmp=a,pos=0; while(tmp){ tmp/=10;len++; } cnt[len]++; tmp=a; while(tmp){ pos++; x[len][pos]+=tmp%10; tmp/=10; } } ll f(int i,int j){ ll res1=0,res2=0; if(i>j){ for(int k=1;k<=j;k++){ res2=(res2+x[j][k]*A[k*2-1]%mod)%mod; res1=(res1+x[i][k]*A[k*2]%mod)%mod; } for(int k=j+1;k<=i;k++) res1=(res1+x[i][k]*A[j+k]%mod)%mod; } else if(i==j){ for(int k=1;k<=i;k++){ res2=(res2+x[j][k]*A[k*2-1]%mod)%mod; res1=(res1+x[i][k]*A[k*2]%mod)%mod; } } else if(i<j){ for(int k=1;k<=i;k++){ res2=(res2+x[j][k]*A[k*2-1]%mod)%mod; res1=(res1+x[i][k]*A[k*2]%mod)%mod; } for(int k=i+1;k<=j;k++) res2=(res2+x[j][k]*A[k+i]%mod)%mod; } return (res1*cnt[j]+res2*cnt[i]%mod)%mod; } int main(){ cin>>n; A[1]=1; for(int i=2;i<=20;i++)A[i]=A[i-1]*10%mod; for(int i=1;i<=n;i++){ cin>>a[i]; calc(a[i]); } ll ans=0; for(int i=1;i<=10;i++) for(int j=1;j<=10;j++) if(cnt[i] && cnt[j]) ans=(ans+f(i,j))%mod; cout<<ans<<endl; }