题目
点这里看题目。
分析
分类讨论。
(gcd(10,p)=1)
此时,设(s(i))为([i,n])这个子串对应的数字,那么就可以得到,任何一个子串([i,j])即为:
[(s(i)-s(j+1)) imes 10^{-(i-j)}
]
对于一个(mod p)为 0 的子串,由于数据范围内的(10^{-(i-j)} otequivpmod p),因此一定有(s(i)=s(j+1))。这就转化成了区间相等对数量的问题,可以离散化之后莫队。
(gcd(10,p) ot=1)
由于(p)是素数,所以(p=2)或(p=5)。
那么直接查询区间中以(2)结尾/以(5)结尾的子串数即可。
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <utility>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> ele;
const int MAXN = 2e5 + 5, MAXS = 505;
template<typename _T>
void read( _T &x )
{
x = 0;char s = getchar();int f = 1;
while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
x *= f;
}
template<typename _T>
void write( _T x )
{
if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
if( 9 < x ){ write( x / 10 ); }
putchar( x % 10 + '0' );
}
ele val[MAXN];
int pure[MAXN], H[MAXN], tot[MAXN], ans[MAXN];
int a[MAXN], cnt[MAXN], ps[MAXN];
int N, Q, res, blk, mod;
char C[MAXN];
struct query
{
int l, r, id, qid;
query() { l = r = id = 0; }
bool operator < ( const query &b ) const { return id == b.id ? ( id & 1 ? r > b.r : r < b.r ) : id < b.id; }
}q[MAXN];
int qkpow( int base, int indx )
{
int ret = 1;
while( indx )
{
if( indx & 1 ) ret = 1ll * ret * base % mod;
base = 1ll * base * base % mod, indx >>= 1;
}
return ret;
}
void add( const int i ) { res += tot[H[i]] ++; }
void sub( const int i ) { res -= -- tot[H[i]]; }
int main()
{
read( mod );
scanf( "%s", C + 1 ), N = strlen( C + 1 );
for( int i = 1 ; i <= N ; i ++ ) a[i] = C[i] - '0';
read( Q );
if( mod == 2 || mod == 5 )
{
for( int i = 1 ; i <= N ; i ++ )
ps[i] = ps[i - 1] + bool( a[i] % mod == 0 ) * i,
cnt[i] = cnt[i - 1] + bool( a[i] % mod == 0 );
while( Q -- )
{
int l, r;
read( l ), read( r );
write( ps[r] - ps[l - 1] - 1ll * ( cnt[r] - cnt[l - 1] ) * ( l - 1 ) ), putchar( '
' );
}
return 0;
}
val[N + 1] = ele( 0, N + 1 );
for( int i = N ; i ; i -- )
val[i] = ele( ( 1ll * a[i] * qkpow( 10, N - i ) % mod + val[i + 1].first ) % mod, i ),
pure[i] = val[i].first;
std :: sort( val + 1, val + 2 + N ), val[0].first = -1;
for( int i = 1, tot = 0 ; i <= N + 1 ; i ++ ) H[val[i].second] = ( tot += val[i].first != val[i - 1].first );
blk = sqrt( N );
for( int i = 1 ; i <= Q ; i ++ )
read( q[i].l ), read( q[i].r ), q[i].r ++, q[i].id = q[i].l / blk, q[i].qid = i;
sort( q + 1, q + 1 + Q );
int l = 1, r = 0, id, qL, qR;
for( int i = 1 ; i <= Q ; i ++ )
{
id = q[i].qid, qL = q[i].l, qR = q[i].r;
while( r < qR ) add( ++ r );
while( qR < r ) sub( r -- );
while( l < qL ) sub( l ++ );
while( qL < l ) add( -- l );
ans[id] = res;
}
for( int i = 1 ; i <= Q ; i ++ ) write( ans[i] ), putchar( '
' );
return 0;
}