Codeforces - 1195D2 - Submarine in the Rybinsk Sea (hard edition) - 组合数学
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) - 组合数学的更多相关文章
- Codeforces - 1195D1 - Submarine in the Rybinsk Sea (easy edition) - 水题
https://codeforc.es/contest/1195/problem/D1 给\(n\)个等长的十进制数串,定义操作\(f(x,y)\)的结果是"从\(y\)的末尾开始一个一个交 ...
- Codeforces Round #574 (Div. 2) D2. Submarine in the Rybinsk Sea (hard edition) 【计算贡献】
一.题目 D2. Submarine in the Rybinsk Sea (hard edition) 二.分析 相比于简单版本,它的复杂地方在于对于不同长度,可能对每个点的贡献可能是有差异的. 但 ...
- Codeforces Round #574 (Div. 2) D1. Submarine in the Rybinsk Sea (easy edition) 【计算贡献】
一.题目 D1. Submarine in the Rybinsk Sea (easy edition) 二.分析 简单版本的话,因为给定的a的长度都是定的,那么我们就无需去考虑其他的,只用计算ai的 ...
- 构造 Codeforces Round #302 (Div. 2) B Sea and Islands
题目传送门 /* 题意:在n^n的海洋里是否有k块陆地 构造算法:按奇偶性来判断,k小于等于所有点数的一半,交叉输出L/S 输出完k个L后,之后全部输出S:) 5 10 的例子可以是这样的: LSLS ...
- codeforces 1195D2-Submarine in the Rybinsk Sea
传送门:QAQQAQ 题意:自己看 思路:就是一个类似于数位DP的东西... 统计a[i]数位分解的数在每一位出现的个数,即分两种讨论: 1.位数小于当前j,则j会出现在q+i,而且计算顺序互换会计算 ...
- 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 ...
- 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 ...
- Codeforces Round #541 (Div. 2) A.Sea Battle
链接:https://codeforces.com/contest/1131/problem/A 题意: 给两个矩形,一个再上一个在下,求两个矩形合并的周围一圈的面积. 思路: 因为存在下面矩形宽度大 ...
- 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 ...
随机推荐
- 原生JS实现图片循环切换
<!-- <!DOCTYPE html> <html> <head> <title>原生JS实现图片循环切换 —— 方法一</title&g ...
- leetcode 003
3. Longest Substring Repeating Character Difficulty:Medium The link: https://leetcode.com/problems/l ...
- Matlab的2D作图
1 plot()函数 画一条线 plot(X,Y) 最基本的例子 x = 0: pi / 100:2 * pi; y = sin(x); figure plot(x,y) 在一张图上画多条线 clc; ...
- php函数漏洞
1.ereg — 正则表达式匹配 此函数遇 %00 截断. <?php $a = $_GET['pwd']; var_dump(ereg ("^[0-9]+$", $a)); ...
- 24.mongodb可视化工具部署——2019年12月19日
2019年10月09日17:05:54 教程链接:https://blog.csdn.net/qq_32340877/article/details/79142129 项目名:adminMongo g ...
- 左右flex布局
修复版本
- SNOI2017 礼物
题解 设前\(n\)个人的礼物个数和为\(F_n\), 那么显然\[F_n = 2 \times F_{n-1} + i^k\] 考虑矩阵快速幂 棘手的问题是:\(i^k\)不是可以直接用矩阵乘法可以 ...
- C++遍历循环多维数组
#include <iostream> using namespace std; int main() { int arr[2][2][2] = {0}; for(auto&&am ...
- [POJ1187] 陨石的秘密
问题描述 公元11380年,一颗巨大的陨石坠落在南极.于是,灾难降临了,地球上出现了一系列反常的现象.当人们焦急万分的时候,一支中国科学家组成的南极考察队赶到了出事地点.经过一番侦察,科学家们发现陨石 ...
- Android逆向之旅---解析编译之后的Dex文件格式
一.前言 新的一年又开始了,大家是否还记得去年年末的时候,我们还有一件事没有做,那就是解析Android中编译之后的classes.dex文件格式,我们在去年的时候已经介绍了: 如何解析编译之后的xm ...