[HNOI2016]大数

题目

  点这里看题目。

分析

  分类讨论。

\(gcd(10,p)=1\)

  此时,设\(s(i)\)\([i,n]\)这个子串对应的数字,那么就可以得到,任何一个子串\([i,j]\)即为:

\[(s(i)-s(j+1))\times 10^{-(i-j)} \]

  对于一个\(\bmod p\)为 0 的子串,由于数据范围内的\(10^{-(i-j)}\not\equiv\pmod p\),因此一定有\(s(i)=s(j+1)\)。这就转化成了区间相等对数量的问题,可以离散化之后莫队。

\(gcd(10,p)\not=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( '\n' );
		}
		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( '\n' );
	return 0;
}
posted @ 2020-06-01 14:32  crashed  阅读(128)  评论(0编辑  收藏  举报