https://codeforces.com/problemset/problem/1195/D2
题意翻译
题目描述
这题与上一个题的不同之处仅在于存在使所有数字 a_1,a_2,\dots,a_na1,a2,…,an 的无长度相等的约束。
SISSIS 学生团队将乘坐潜水艇去旅游,他们的目标是位于大雷宾斯克 (Rybinsk)(Rybinsk) 海底沉船中的古代宝藏。不幸的是,学生们不知道船的坐标,因此他们要求 MeshanyaMeshanya(一位世袭魔法师)来帮助他们。MeshanyaMeshanya 同意帮助他们,但前提是他们得解决了 MeshanyaMeshanya 的问题。
让我们用一个函数 f(a_1a_2\dots a_{p-1}a_p,b_1b_2\dots b_{p-1}b_p)f(a1a2…ap−1ap,b1b2…bp−1bp) 来交替两个数字的各位数码,其中 a_1,a_2,\dots,a_pa1,a2,…,ap 和 b_1,b_2,\dots,b_pb1,b2,…,bp 是以十进制表示的两个整数的数码,不含前导零。
换句话说,函数 f(x,y)f(x,y) 通过将数字 xx 和 yy 的各位数码从最低位数写到较高位数字,从数字 yy 开始,交替地插入数字 xx 和 yy。该函数的结果也是从右到左构建的(即从较低的数字到较旧的数字)。如果其中一个参数(不妨设为 xx)的数字已写完,则写下另一个参数(即 yy)的剩余数字,下面我们来看几个例子熟悉一下。
f(1111, 2222) = 12121212f(1111,2222)=12121212
f(7777, 888) = 7787878f(7777,888)=7787878
f(33, 44444) = 4443434f(33,44444)=4443434
f(555, 6) = 5556f(555,6)=5556
f(111, 2222) = 2121212f(111,2222)=2121212
一般的,如果 p \ge qp≥q,那么 f(a_1 \dots a_p, b_1 \dots b_q) = (a_1 a_2 \dots a_{p - q + 1} b_1 a_{p - q + 2} b_2 \dots a_{p - 1} b_{q - 1} a_p b_q)_{(10)}f(a1…ap,b1…bq)=(a1a2…ap−q+1b1ap−q+2b2…ap−1bq−1apbq)(10) MishanyaMishanya 为您提供一个由 nn 个整数组成的数组 \{a_i\}{ai}。你的任务是帮助学生们计算 \sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{n} f(a_i, a_j) \mod 998244353i=1∑nj=1∑nf(ai,aj)mod998244353
输入格式
输入的第一行包含一个整数 n(1 \le n \le 100000)n(1≤n≤100000)。输入的第二行包含 nn 个整数 a_1,a_2,\dots,a_n(1\le a_i\le10^9)a1,a2,…,an(1≤ai≤109),所有数字长度相同,它们即位数相等。
输出格式
答案模 998244353998244353。
输入输出样例
输入 #1复制
3 12 3 45
输出 #1复制
12330
输入 #2复制
2 123 456
输出 #2复制
1115598
思路:暴力去做是n^2的。像这种题比较经典的转化是枚举位去优化。
统计每个数的每一位,同时枚举和每一个长度为1~10的数字进行f的贡献
比如n=2
12 231. 那么过程是f(12,12)+f(12,231)+f(231,12)+f(231,231)
考虑枚举到12,12和长度为2,3的数字去统计过程。
比如12 和231,12的2的贡献在f(12,231)的时候贡献是 21321的十位,而题目求和是n^2的求和,光统计这个不够,12的2在f(231,12)的时候也有贡献,是2的个位。这里在模拟之后得出来分别是siz*pw[cur*2-1]*p和siz*pw[cur*2-2]*p。
siz是长度为1/2/3/...10的个数,pw[]是预处理出来的十进制的阶乘。
然后比如考虑231和12,231的2的贡献在f(231,12)的时候贡献的是23112,这个2在万位。而题目求和是n^2的求和,光统计这个不够,231的2在f(12,231)的时候是21321,也是万位。综合一下是乘2的过程。
挺好一题
#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
typedef long long LL;
const int N = 100100;
const int mod = 998244353;
LL a[N], cnt[100], sz[N];
LL pw[100];
LL times=0;
LL cal(LL x,LL len,LL siz)
{
LL cur=0;
LL ans=0;
// debug(len);
// debug(siz);
while(x)
{
cur++;
LL p=x%10;
// debug(p);
x/=10;
times++;
if(cur<=len){
ans=(ans%mod+siz*pw[cur*2-1]*p%mod)%mod;
// cout<<"times: "<<"p="<<p<<" "<<siz*pw[cur*2-1]*p<<endl;
ans=(ans%mod+siz*pw[cur*2-2]*p%mod)%mod;
// cout<<"times: "<<"p="<<p<<" "<<siz*pw[cur*2-2]*p<<endl;
//cout<<"siz*pw[(cur*2)]*p%mod="<<siz*pw[(cur*2)]*p%mod<<endl;
//debug(ans);
}
else{
ans=(ans%mod+2*siz*p*pw[len+cur-1]%mod)%mod;
// cout<<"times: "<<"p="<<p<<" "<<siz*p*pw[len+cur-1]<<endl;
//debug(ans);
}
}
return ans;
}
LL getlen(LL x)
{
LL l=0;
while(x)
{
l++;
x/=10;
}
return l;
}
int main() {
LL n;
scanf("%lld", &n);
pw[0] = 1;//因为后面用while(x)取位,所以初始化p[0]=1;
for (LL i = 1; i <= 31; i++) pw[i] = pw[i-1] * 10 % mod;
for (LL i = 1; i <= n; i++) {
scanf("%lld",&a[i]);
cnt[getlen(a[i])]++;
}
LL res = 0;
for (LL i = 1; i <= n; i++) {
LL b = a[i];
for(LL j=1;j<=10;j++){
if(cnt[j])
{
res=(res%mod+cal(b,j,cnt[j])%mod)%mod;
}
}
}
printf("%lld\n", res);
}