https://codeforc.es/problemset/problem/1195/D2

很明显可以看出,任意一个长度为\(l_1\)的数串\(s_1\)和任意一个长度为\(l_2\)的数串\(s_2\)在\(f(s_1,s_2)\)中每个位的贡献的位数是一样的。稍微推一推可以知道,\(calcx\_ijk\)和\(calcy\_ijk\)的公式。然后暴力统计一波各个长度的数串有几个就可以了。小心溢出。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; ll a[100005];
ll di[100005][11];
int cntws[11]; ll gx[11][11][11];
ll gy[11][11][11]; const ll mod = 998244353; int ws(ll x) {
int cnt = 0;
while(x) {
//cout<<x<<" ";
cnt++;
x /= 10;
//cout<<cnt<<endl;
}
return cnt;
} ll ans; ll calc_base(int i,int k){
ll res=0;
for(int j=1;j<=10;j++){
res=(res+1ll*cntws[j]*gx[i][j][k]%mod)%mod;
res=(res+1ll*cntws[j]*gy[i][j][k]%mod)%mod;
}
//cout<<"i="<<i<<" k="<<k<<" res="<<res<<endl;
return res;
} ll calc(ll x) {
ll res = 0;
int i=ws(x);
for(int k=1;k<=i;k++){
ll r = x%10;
res = (res + calc_base(i,k)* r % mod) % mod;
x /= 10;
}
return res % mod;
} ll p10[23]; ll calc_ijk(int i, int j, int k) {
if(k <= j) {
return p10[k * 2];
} else {
return p10[j + k];
}
} ll calc_ijk2(int i, int j, int k) {
if(k <= j) {
return p10[k * 2 - 1];
} else {
return p10[j + k];
}
} void init_gx() {
memset(gx, 0, sizeof(gx));
//gx[i][j][k]i是x,j是y的时候,导致i的第k位贡献的位数
//gy[i][j][k]i是x,j是y的时候,导致j的第k位贡献的位数
for(int i = 1; i <= 10; i++) {
for(int j = 1; j <= 10; j++) {
for(int k = 1; k <= i; k++) {
gx[i][j][k] = calc_ijk(i, j, k);
}
}
}
memset(gy, 0, sizeof(gy));
//gx[i][j]i是x,j是y的时候,导致i贡献的位数
//gy[i][j]i是x,j是y的时候,导致j贡献的位数
for(int i = 1; i <= 10; i++) {
for(int j = 1; j <= 10; j++) {
for(int k = 1; k <= i; k++) {
gy[i][j][k] = calc_ijk2(i, j, k);
}
}
}
} int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out", "w", stdout);
#endif // Yinku
p10[1] = 1;
for(int i = 2; i <= 21; i++) {
p10[i] = p10[i - 1] * 10ll % mod;
//cout<<p10[i]<<endl;
}
int n;
init_gx();
for(int i = 1; i <= 2; i++) {
for(int j = 1; j <= 2; j++) {
for(int k = 1; k <= i; k++) {
gx[i][j][k] %= mod;
gy[i][j][k] %= mod;
//printf("%lld ",gx[i][j][k]);
//printf("%lld",gy[i][j][k]);
}
//printf("\n");
}
//printf("\n");
}
while(~scanf("%d", &n)) {
memset(cntws, 0, sizeof(cntws));
for(int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
cntws[ws(a[i])]++;
//cout<<ws(a[i])<<endl;
}
/*for(int i = 1; i <= 10; ++i) {
//cout<<cntws[i]<<endl;
}*/
ans = 0;
for(int i = 1; i <= n; i++) {
ans = (ans + calc(a[i])) % mod;
//printf("ans=%lld\n", ans % mod);
}
printf("%lld\n", ans % mod);
}
}

发现其实可以缩写成下面的形式:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int mod = 998244353; int a[100005];
int lena[100005];
int cntlen[11]; int g[11][11][11]; int len(int x) {
int cnt = 0;
while(x) {
cnt++;
x /= 10;
}
return cnt;
} ll ans; ll calc_base(int i, int k) {
ll res = 0;
for(int j = 1; j <= 10; j++)
res = (res + 1ll * g[i][j][k] * cntlen[j] % mod) % mod;
return res;
} ll calc(int x, int lenx) {
ll res = 0;
for(int k = 1; k <= lenx; k++) {
int r = x % 10;
res = (res + calc_base(lenx, k) * r % mod) % mod;
x /= 10;
}
return res % mod;
} int p10[21]; void init_g() {
memset(g, 0, sizeof(g));
//g[i][j][k]是两个数分别是i位,j位时候,导致长度为i的第k位发生的贡献
for(int i = 1; i <= 10; i++)
for(int j = 1; j <= 10; j++)
for(int k = 1; k <= i; k++)
g[i][j][k] = (p10[k + ((k <= j) ? k : j)] + p10[k + ((k <= j) ? (k - 1) : j)]) % mod;
} void init_p10() {
p10[1] = 1;
for(int i = 2; i <= 20; i++) {
p10[i] = p10[i - 1] * 10ll % mod;
}
} int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out", "w", stdout);
#endif // Yinku
init_p10();
init_g();
int n;
while(~scanf("%d", &n)) {
memset(cntlen, 0, sizeof(cntlen));
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
lena[i] = len(a[i]);
cntlen[lena[i]]++;;
}
ans = 0;
for(int i = 1; i <= n; i++) {
ans = (ans + calc(a[i], lena[i])) % mod;
}
printf("%lld\n", ans);
}
}

Codeforces - 1195D2 - Submarine in the Rybinsk Sea (hard edition) - 组合数学的更多相关文章

  1. Codeforces - 1195D1 - Submarine in the Rybinsk Sea (easy edition) - 水题

    https://codeforc.es/contest/1195/problem/D1 给\(n\)个等长的十进制数串,定义操作\(f(x,y)\)的结果是"从\(y\)的末尾开始一个一个交 ...

  2. Codeforces Round #574 (Div. 2) D2. Submarine in the Rybinsk Sea (hard edition) 【计算贡献】

    一.题目 D2. Submarine in the Rybinsk Sea (hard edition) 二.分析 相比于简单版本,它的复杂地方在于对于不同长度,可能对每个点的贡献可能是有差异的. 但 ...

  3. Codeforces Round #574 (Div. 2) D1. Submarine in the Rybinsk Sea (easy edition) 【计算贡献】

    一.题目 D1. Submarine in the Rybinsk Sea (easy edition) 二.分析 简单版本的话,因为给定的a的长度都是定的,那么我们就无需去考虑其他的,只用计算ai的 ...

  4. 构造 Codeforces Round #302 (Div. 2) B Sea and Islands

    题目传送门 /* 题意:在n^n的海洋里是否有k块陆地 构造算法:按奇偶性来判断,k小于等于所有点数的一半,交叉输出L/S 输出完k个L后,之后全部输出S:) 5 10 的例子可以是这样的: LSLS ...

  5. codeforces 1195D2-Submarine in the Rybinsk Sea

    传送门:QAQQAQ 题意:自己看 思路:就是一个类似于数位DP的东西... 统计a[i]数位分解的数在每一位出现的个数,即分两种讨论: 1.位数小于当前j,则j会出现在q+i,而且计算顺序互换会计算 ...

  6. Codeforces Round #302 (Div. 2) B. Sea and Islands 构造

    B. Sea and Islands Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/544/p ...

  7. Codeforces Round #380 (Div. 2)/729D Sea Battle 思维题

    Galya is playing one-dimensional Sea Battle on a 1 × n grid. In this game a ships are placed on the ...

  8. Codeforces Round #541 (Div. 2) A.Sea Battle

    链接:https://codeforces.com/contest/1131/problem/A 题意: 给两个矩形,一个再上一个在下,求两个矩形合并的周围一圈的面积. 思路: 因为存在下面矩形宽度大 ...

  9. Codeforces Round #258 (Div. 2) D. Count Good Substrings —— 组合数学

    题目链接:http://codeforces.com/problemset/problem/451/D D. Count Good Substrings time limit per test 2 s ...

随机推荐

  1. Rsync安装部署

    Rsync安装部署 1.Rsync  简介 Rsync  是一款开源的.快速的 多功能的 可以实现全量以及增量的本地或者是远程的数据同步备份的优秀工具,并且可以不进行改变原有的数据属性信息,实现数据的 ...

  2. linux 配置 Sersync

    [root@SERSYNC sersync]# cp conf/confxml.xml conf/confxml.xml.bak.$(date +%F) [root@SERSYNC sersync]# ...

  3. SpringBoot 利用freemaker生成静态页面

    1. <!-- freemarker模板 --> <dependency> <groupId>org.springframework.boot</groupI ...

  4. 记录ViewPager配合Fragment使用中遇到的一个问题

    java.lang.IllegalStateException: FragmentManager is already executing transactions 如图所示: 当调用 notifyD ...

  5. UVa 10054 : The Necklace 【欧拉回路】

    题目链接 题目大意:我的妹妹有一串由各种颜色组成的项链. 项链中两个连续珠子的接头处共享同一个颜色. 如上图, 第一个珠子是green+red, 那么接这个珠子的必须以red开头,如图的red+whi ...

  6. What code you will get when you create a wcf library

    创建wcf服务库的时候,系统自动生成的代码 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”. [ServiceContract] publ ...

  7. HTML5 新属性的讲解

    1.选择器: 标签选择器: class选择器: id选择器: 后代选择器:div li div下所有li 子代选择器:div>li div的所有子一代 li 元素 交集选择器:div.class ...

  8. 移动端调试 — 安卓机+chrome

    移动端开发时,我们常使用chrome自带的模拟器,模拟各种手机设备. 但模拟毕竟是模拟,当开发完毕,使用真机访问页面出现问题时如何调试呢? 下面介绍一种针对Android机的调试方法 1. 在pc和a ...

  9. C++ lower_bound 与 upper_bound 函数

    头文件: #include  <algorithm> 二分查找的函数有 3 个: 参考:C++ lower_bound 和upper_bound lower_bound(起始地址,结束地址 ...

  10. java 创建文件 呵呵 成功

    package aaa;import java.util.Date;import java.util.regex.Matcher;import java.util.regex.Pattern;impo ...