Codeforces Round #574 (Div. 2) D2 Submarine in the Rybinsk Sea (hard edition)

题目链接

This problem differs from the previous one only in the absence of the constraint on the equal length of all numbers a1,a2,…,an.

A team of SIS students is going to make a trip on a submarine. Their target is an ancient treasure in a sunken ship lying on the bottom of the Great Rybinsk sea. Unfortunately, the students don’t know the coordinates of the ship, so they asked Meshanya (who is a hereditary mage) to help them. He agreed to help them, but only if they solve his problem.

Let’s denote a function that alternates digits of two numbers f(a1a2…ap−1ap,b1b2…bq−1bq), where a1…ap and b1…bq are digits of two integers written in the decimal notation without leading zeros.

In other words, the function f(x,y) alternately shuffles the digits of the numbers x and y by writing them from the lowest digits to the older ones, starting with the number y. The result of the function is also built from right to left (that is, from the lower digits to the older ones). If the digits of one of the arguments have ended, then the remaining digits of the other argument are written out. Familiarize with examples and formal definitions of the function below.

For example:
f(1111,2222)=12121212
f(7777,888)=7787878
f(33,44444)=4443434
f(555,6)=5556
f(111,2222)=2121212
Formally,

if p≥q then f(a1…ap,b1…bq)=a1a2…ap−q+1b1ap−q+2b2…ap−1bq−1apbq;
if p<q then f(a1…ap,b1…bq)=b1b2…bq−pa1bq−p+1a2…ap−1bq−1apbq.
Mishanya gives you an array consisting of n integers ai, your task is to help students to calculate ∑ni=1∑nj=1f(ai,aj) modulo 998244353.

Input
The first line of the input contains a single integer n (1≤n≤100000) — the number of elements in the array. The second line of the input contains n integers a1,a2,…,an (1≤ai≤109) — the elements of the array.

Output
Print the answer modulo 998244353.

Example1:

3
12 3 45
12330

Example2:

2
123 456
1115598

题意:
大致意思就是,一个函数 f(x,y) 计算的是,先从y开始,取y的最后一位,该值为初值,舍掉,再取x的最后一位,放到初值的左侧,再舍掉,一直循环直到有一个数字为0,把另外一个数字的全部剩余数字放到值的左侧,构成一个新的数,求:

sum=0;
for(int i=1;i<=n;i++){
	for(int j=1;j<=n;j++){
		sum+=f(arr[i],arr[j]);
	}
}
sum%=mod;

思路:
某一个数a[i]在执行题目描述中的操作时,实际上是把自己的每一位数字分离出来
然后乘上当前所在位置的指数的幂(ps:指数每次增长2)
因为数字a[i]与相同位数的数字操作时,位置相同
与不同位数的数字操作时,位置不同
数字最大长度为10位
所以可以遍历所有n个数字
每个数字对每一个位数的数字运算的结果乘以总共多少个这么长的数字
求和取模即可

代码1:

#include <bits/stdc++.h>
 
using namespace std;
 
#define MOD 998244353
 
int n, a[100005], cnt[15];
long long ans, po[30];
 
int main() {
	po[0] = 1;
	for (int i = 1; i < 30; i++)
		po[i] = po[i - 1] * 10 % MOD;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", a + i);
		cnt[to_string(a[i]).size()]++;
	}
	for (int i = 0; i < n; i++) {
		//代码原理
		//某一个数a[i]在执行题目描述中的操作时,实际上是把自己的每一位数字分离出来
		//然后乘上当前所在位置的指数的幂(ps:指数每次增长2)
		//因为数字a[i]与相同位数的数字操作时,位置相同
		//与不同位数的数字操作时,位置不同
		//数字最大长度为10位 
		//所以可以遍历所有n个数字
		//每个数字对每一个位数的数字运算的结果乘以总共多少个这么长的数字
		//求和取模即可 
		string s = to_string(a[i]);
		for (auto& j : s)
			j -= '0';
		for (int j = 1; j <= 10; j++) {
			long long sum = 0;
			for (int k = s.size() - 1, at = 0, left = j; k >= 0; k--, at++) {
				if (left) {
					at++;
					left--;
				}
				sum += po[at] * s[k];
			}
			for (int k = s.size() - 1, at = 0, left = j; k >= 0; k--, at++) {
				sum += po[at] * s[k];
				if (left) {
					at++;
					left--;
				}
			}
			(ans += sum % MOD * cnt[j]) %= MOD;
		}
	}
	printf("%lld\n", ans);
}

代码2:

#include<bits/stdc++.h>
using namespace std;
const int mod = 998244353;
int n;
typedef long long ll;
ll arr[110000];
ll po[30];
int len[20];
int countLength(ll num) {
	int res = 0;
	while (num) {
		res++;
		num /= 10;
	}
	return res;
}
int main()
{
	po[0] = 1;
	for (int i = 1; i < 30; i++) {
		po[i] = po[i - 1] * 10 % mod;
	}
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%lld", arr + i);
	}
	for (int i = 0; i < n; i++) {
		len[countLength(arr[i])]++;
	}
	ll res = 0;
	int k, ind, length;
	for (int i = 0; i < n; i++) {
		ll t;
		int llen = countLength(arr[i]);
		for (int j = 1; j <= 10; j++) {
			ll sum = 0;
			t = arr[i];
			for (length = j, ind = 0; t; ind++, t /= 10) {
				sum += po[ind] * (t % 10);
				if (length) {
					ind++;
					length--;
				}
			}
			t = arr[i];
			for (length = j, k = 0, ind = 0; t; ind++, t /= 10) {
				if (length) {
					ind++;
					length--;
				}
				sum += po[ind] * (t % 10);
			}
			res += (sum%mod*len[j]) % mod;
			res %= mod;
		}

	}
	printf("%lld", res);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值