Submarine in the Rybinsk Sea (hard edition) CodeForces - 1195D2 (思维)

题目链接

题意:定义函数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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值