UVALive 7327【模拟】

题意:
每次方案一个或多个子序列;
每个子序列要整除m
认为分割不同,子序列边界的不同就是不同;
1246有4个
1246
12 46
124 6
12 4 6
思路:
先从整体考虑,因为取膜适用于加法,所以一个数拆分成两个数%m==0就代表这个数%m一定=0;
再考虑把原串划分成两段,当且仅当某个前缀组成的数能被m整除时,原串才能被分成两段.
划成多段同理.
求出有多少地方能被切割,结果就是 2^(res-1). 就是相当于枚举每个位置切割or不切割结果.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

typedef long long LL;
const int N=3e5+10;
const LL mod=1e9+7;
char s[N];

LL cal(LL g,LL x)
{
    LL ans=1;
    while(g)
    {
        if(g%2) ans=(ans*x)%mod;
        x=(x*x)%mod;
        g>>=1;
    }
    return ans;
}

int main()
{
    LL n;
    LL m;
    while(~scanf("%lld%lld",&n,&m))
    {
        LL res=0;
        LL temp=0;
        scanf("%s",s);
        for(LL i=0;i<n;i++)
        {
            temp=(temp*10LL+s[i]-'0')%m;
            if(!temp)
                res++;
        }
        if(temp)
        {
            puts("0");
            continue;
        }
        printf("%lld
",cal(res-1,2));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934785.html