题目大意
题目描述
给定一个长度为 n 的正整数数组,求有多少个非空连续子数组满足以下条件:子数组内所有元素的和,能够被该子数组中所有元素包含的数字字符的最大值整除。
(注:数字字符指组成数字的 0∼9。例如,数组 [2025, 11, 15] 中包含的数字字符有 0,1,2,5,其最大值为 5。)
输入格式
第一行包含一个整数 T(1≤T≤104),表示测试用例的数量。
对于每个测试用例:
第一行包含一个整数 n(1≤n≤105),表示数组长度。
第二行包含 n 个正整数 x1,x2,…,xn(1≤xi≤109),表示数组元素。
保证所有测试用例中 n 的总和不超过 105。
输出格式
对于每个测试用例,输出一行一个整数,表示满足条件的非空子数组数量。
样例输入
1 2 3 4 5
| 2 3 213 12 21 7 314 880 246 170 493 474 129
|
样例输出
样例解释
以第一个测试用例 [213, 12, 21] 为例,考察其所有非空子数组:
-
[213]:包含数字 1,2,3,最大数字为 3。子数组元素和为 213,213mod3=0,满足条件。
-
[12]:包含数字 1,2,最大数字为 2。子数组元素和为 12,12mod2=0,满足条件。
-
[21]:包含数字 1,2,最大数字为 2。子数组元素和为 21,21mod2=0,不满足条件。
-
[213, 12]:包含数字 1,2,3,最大数字为 3。子数组元素和为 213+12=225,225mod3=0,满足条件。
-
[12, 21]:包含数字 1,2,最大数字为 2。子数组元素和为 12+21=33,33mod2=0,不满足条件。
-
[213, 12, 21]:包含数字 1,2,3,最大数字为 3。子数组元素和为 213+12+21=246,246mod3=0,满足条件。
满足条件的子数组共有 4 个。
思路讲解
≤d 比=d 好计数得多,那为什么不使用 f(≤d)-f(≤d-1) 得到 f(=d) 呢?
不过,要注意到,就是光一个 d 是不够描述这个 f 函数的。
定义 $ f(≤d,big_d)$ 指的是最大 digit 是 ≤d 而且可以被 bigd 整除的这个子段数量。
因此,不难发现 $ f(=d,big_d)=f(≤d,big_d)-f(≤d-1,big_d)$。
使用这一容斥方法解决该问题,是因为我们发现在编程中,我们发现,很难对 最大 digit=d 进行计数(你要是不信的话可以自此试试)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| for (int big_d=1;big_d<=9;++big_d) { vector<ll> F(10+2); for (int d=big_d-1;d<=big_d;++d) { vector<ll> R(big_d); for (int i=1;i<=N;++i) { if (mx_d[i]>d) { R.assign(big_d,0); continue; } ll rem=A[i]%big_d; rotate(R.rbegin(),R.rbegin()+rem,R.rend()); R[rem]++; F[d]+=R[0];
} } ans+=F[big_d]-F[big_d-1]; }
|
AC代码
AC
https://codeforces.com/gym/106380/submission/366441214
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
#include <bits/stdc++.h> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<" = ["<<var<<"]"<<"\n"; #define debug1d(a) \ cerr << #a << " = ["; \ for (int i = 0; i < (int)(a).size(); i++) \ cerr << (i ? ", " : "") << a[i]; \ cerr << "]\n"; #define debug2d(a) \ cerr << #a << " = [\n"; \ for (int i = 0; i < (int)(a).size(); i++) \ { \ cerr << " ["; \ for (int j = 0; j < (int)(a[i]).size(); j++) \ cerr << (j ? ", " : "") << a[i][j]; \ cerr << "]\n"; \ } \ cerr << "]\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using i128 = __int128; using CD = complex<double>;
static constexpr ll MAXN = (ll)1e6+10, INF = (1ll<<61)-1; static constexpr ll mod = 998244353; static constexpr double eps = 1e-8; const double pi = acos(-1.0);
ll lT,testcase;
void Solve() { ll N; cin >> N; vector<ll> A(N+2); vector<ll> mx_d(N+2); for (int i=1;i<=N;++i) { cin>>A[i]; string s=to_string(A[i]); mx_d[i]=*max_element(all(s))-'0'; } ll ans=0;
for (int big_d=1;big_d<=9;++big_d) { vector<ll> F(10+2); for (int d=big_d-1;d<=big_d;++d) { vector<ll> R(big_d); for (int i=1;i<=N;++i) { if (mx_d[i]>d) { R.assign(big_d,0); continue; } ll rem=A[i]%big_d; rotate(R.rbegin(),R.rbegin()+rem,R.rend()); R[rem]++; F[d]+=R[0];
} } ans+=F[big_d]-F[big_d-1]; }
cout<<ans<<"\n"; }
signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); #ifdef LOCAL cout.setf(ios::unitbuf); #endif
cin >> lT; for (testcase=1;testcase<=lT;++testcase) Solve(); return 0; }
|
心路历程(WA,TLE,MLE……)