CodeForces 1195D Submarine in the Rybinsk Sea (算贡献)
CodeForces 1195D Submarine in the Rybinsk Sea (算贡献)
思路:
n的大小为1e5,n^2枚举不现实,考虑每个数的贡献。
先看easy版本的,即所有的数长度都相同。那么每个数可以有n次在前面,n次在后面。
比如说12,33:
12和12组合得到1122,12和33得到1323:在这两个里12的贡献都是1020(只看前面的部分)
12和12组合得到1122,33和12组合得到3132:在这两个里12的贡献都是102(只看后面的部分)
也就是说12对答案的贡献为n*(102+1020)(n=2)。
这样枚举每一个数计算就可以。
再看hard版本,所有的数长度都不同。但是每个数对于不同长度的贡献都是确定的,可以枚举所有的长度(1-10),求一个贡献的总和。然后就不是很会实现。
代码:
easy
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define x first
#define y second
const int maxn=1e5+10;
const ll mod=998244353;
ll a[25];
ll cul(ll x){
ll res=0,cnt=0,t=x,tot=0;
while(t){
cnt++;t/=10;
}
t=x;
for(int i=0;i<cnt;i++){
a[tot++]=t%10;
a[tot++]=t%10;
t/=10;
}
for(int i=2*cnt-1;i>=0;i--){
res=(res*10+a[i])%mod;
}
return res;
}
int main(){
ll res=0;
int n;cin>>n;
for(int i=1;i<=n;i++){
ll x;cin>>x;
res=(res+cul(x)*n%mod)%mod;
}
cout<<res<<endl;
return 0;
}
hard
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
const ll mod=998244353;
ll p[35],len[15];
ll a[maxn],b[35];
ll get_len(ll x){
return (ll)(log10(x)+1);
}
int main(){
p[0]=1;
for(int i=1;i<=32;i++)
p[i]=p[i-1]*10%mod;
int n;cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
len[get_len(a[i])]++;
//cout<<get_len(a[i])<<endl;
}
ll res=0;
for(int i=1;i<=n;i++){
int cnt=0;ll t=a[i];
while(t){//把当前每一位数都分离出来
b[++cnt]=t%10;t/=10;
}
for(int j=1;j<=10;j++){//枚举所有的长度
ll sum=0;
for(int k=1;k<=cnt;k++){
sum=(sum+b[k]*p[k-1+min(j,k)]%mod)%mod;//该数在前面的贡献
sum=(sum+b[k]*p[k-1+min(j,k-1)]%mod)%mod;//该数在后面的贡献
}
res=(res+sum*len[j])%mod;//对长度为j的数贡献都相同,乘积即可
}
}
cout<<res<<endl;
return 0;
}