• [HNOI2016]大数


    题目

      点这里看题目。

    分析

      分类讨论。

    (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;
    }
    
  • 相关阅读:
    [编程] 正则表达式
    [游戏] PhysX物理引擎(编程入门)
    [PHP] visitFile()遍历指定文件夹
    [D3D] 用PerfHUD来调试商业游戏
    [C,C++] 妙用0元素数组实现大小可变结构体
    [D3D] DirectX SDK 2006学习笔记1——框架
    [JS] 图片浏览器(兼容IE,火狐)
    [C#(WinForm)] 窗体间传值方法
    [ASP.NET] 提示错误:The server has encountered an error while loading an application during the processing your request
    [JS] 火狐得到文件的绝对路径(暂时的方法)
  • 原文地址:https://www.cnblogs.com/crashed/p/13025035.html
Copyright © 2020-2023  润新知