BZOJ 4277 ONTAK2015 Cięcie

题目大意:给定一个数字串,要求分成三段 A,B,C ,满足 A,B,C 都不含前导零且 p|A,q|B,r|C
“不含前导零”这个条件只是在增加细节,我们无视他
首先枚举 A B的分界线,设分界线两侧的部分分别是 L R,那么记录 cnti 表示 L0(mod p) Ri(mod q) (L,R) 的个数
然后倒着枚举 BC 的分界线,对于每个位置,首先删除与 R C重合的 (L,R) ,然后将 RC10|C|0(mod q) RC(mod q) (L,R) 记录答案。显然这个值就是 cntC mod q
然后加上“不含前导零”这个条件就是多了一堆细节。。。慢慢讨论吧艹

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1001001
using namespace std;
int n,p,q,r;
long long ans;
char s[M];
int a[M],L[M],R[M],cnt[100100];
int main()
{
    int i,pow10_mod_q=1,pow10_mod_r=1;
    cin>>n>>p>>q>>r;
    scanf("%s",s+1);
    for(i=1;i<=n;i++)
    {
        a[i]=s[i]-'0';
        L[i]=(L[i-1]*10+a[i])%p;
    }
    for(i=n;i;i--,(pow10_mod_q*=10)%=q)
        R[i]=(R[i+1]+a[i]*pow10_mod_q)%q;
    for(i=1;i<n;i++)
    {
        if( a[1]==0 && i!=1 )
            continue;
        if( a[i+1]==0 )
            continue;
        if( L[i]==0 )
            cnt[R[i+1]]++;
    }
    int C_mod_q=0,C_mod_r=0;
    for(pow10_mod_q=1,i=n;i>=3;i--,(pow10_mod_q*=10)%=q,(pow10_mod_r*=10)%=r)
    {
        (C_mod_q+=a[i]*pow10_mod_q)%=q;
        (C_mod_r+=a[i]*pow10_mod_r)%=r;
        if( a[i]!=0 && L[i-1]==0 )
            cnt[R[i]]--;
        if( a[i]!=0 || i==n )
            if(C_mod_r==0)
                ans+=cnt[C_mod_q];
        if( C_mod_r==0 && a[i-1]==0 && L[i-2]==0 && (a[1]!=0||i==2) && (a[i]!=0||i==n) )
            ++ans;
    }
    cout<<ans<<endl;
    return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值