题意是给定一个环,每个位置上有一个数字,问有多少个连续子串满足拼接数字后是给定数字K的倍数
n<=5e4,K<=200,a[i]∈[1,1000]
(((也是水题(((
一看K到200就大概知道怎么做了
我的做法比较朴素,先把序列扩展到2n,令p[i]为a[1...i]拼接后模K的值
对于每个i,满足条件的区间为p[i]−p[j−1]∗10i−j%K=0
发现当i加一的时候之前的所有p[j]都要乘10再模K
于是令cnt[i]表示当前满足p[j−1]∗10i−j%K=i的j的个数
每次扫一遍cnt数组,cnt1[i∗10%K]=cnt[i]
当i大于n时要把i−n位置的数字删掉
然后最后的答案要减掉i=n时统计的答案,因为包含在[1,n]的答案会在[n+1,n+n]中再统计一次
O(2nk)
用快速幂T了一发改成预处理10i%K才过了
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
#include <bitset>
#include <cstdlib>
using namespace std;
#define pb push_back
#define pii pair<int, int>
#define mp make_pair
#define ull unsigned long long
#define null NULL
#define PI M_PI
#define sc(x) scanf("%d", &x)
#define sc64(x) scanf("%I64d", &x)
#define scln(x) scanf("%d\n", &x)
#define sc64ln(x) scanf("%I64d\n", &x)
#define pr(x) printf("%d", x)
#define prs(x) printf("x")
#define prln(x) printf("%d\n", x)
#define prsp(x) printf("%d ", x)
#define pr64(x) printf("%I64d", x)
#define pr64ln(x) printf("%I64d\n", x)
#define pr64sp(x) printf("%I64d ", x)
#define rep(i,n) for (int i = 1;i <= (n); ++i)
#define repr(i,n) for (int i = (n);i > 0; --i)
#define repab(i,a,b) for (int i = a;i <= b; ++i)
#define Rep(i,n) for (int i = 0;i < (n); ++i)
#define Repr(i,n) for (int i = (n)-1;i >= 0; --i)
#define Repab(i,a,b) for (int i = a;i < b; ++i)
#define fi first
#define se second
#define SET(__set, val) memset(__set, val, sizeof __set)
typedef long double ld;
typedef long long ll;
typedef pair<ll, ll> pll;
template<class T> T gcd(T a, T b){if(!b)return a;return gcd(b,a%b);}
template<class T> T power(T a, T b){T res(1);while(b){if(b&1)res=res*a;a=a*a;b>>=1;}return res;}
template<class T> T powerM(T a, T b, T mod){T res(1);while(b){if(b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}
const int infi = 2147483647;
const ll infl = 9223372036854775807;
#define N 111000
#define M 200
int n, m, k, T;
int cnt[2][M],a[N],p[N];
int getlen(int x){
int res=0;
while(x){
res++,x/=10;
}
return res;
}
int shi[N<<1];
int main(){
while (~sc(n)){
sc(k);
shi[0] = 1;
rep(i,4*n)
shi[i] = shi[i-1]*10%k;
rep(i,n){
sc(a[i]);
a[i+n]=a[i];
}
SET(cnt,0);
int flag=0;
m = 0;
ll ans = 0, ans1 = 0;
cnt[flag][0] = 1;
rep(i,n*2){
int len = getlen(a[i]);
if(i<=n)m+=len;
p[i] = (p[i-1]*shi[len]+a[i])%k;
SET(cnt[flag^1],0);
Rep(j,k)
if(cnt[flag][j]>0)
cnt[flag^1][j*shi[len]%k] += cnt[flag][j];
flag ^= 1;
ans += cnt[flag][p[i]];
cnt[flag][p[i]]++;
if(i>=n){
int now = shi[m]*p[i-n]%k;
cnt[flag][now]--;
}
if(i==n)ans1 = ans;
}
pr64ln(ans-ans1);
}
return 0;
}