第十四届华科校赛 B-Beautiful Trees Cutting(数论:快速幂+除法取模)

链接:https://www.nowcoder.com/acm/contest/106/B
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
 64bit IO Format: %lld

题目描述
      It’s universally acknowledged that there’re innumerable trees in the campus of HUST.  
      One day Xiao Ming is walking on a straight road and sees many trees line up in the right side. Heights of each tree which is denoted by a non-negative integer from 0 to 9 can form a tree string. It's very surprising to find that the tree string can be represent as an initial string repeating K times. Now he wants to remove some trees to make the rest of the tree string looks beautiful. A string is beautiful if and only if the integer it represents is divisible by five. Now he wonders how many ways there are that he could make it. 
       Note that when we transfer the string to a integer, we ignore the leading zeros. For example, the string “00055” will be seen as 55. And also pay attention that two ways are considered different if the removed trees are different. The result can be very large, so printing the answer (mod 1000000007) is enough. And additionally, Xiao Ming can't cut down all trees.  
输入描述:
The first line contains a single integer K, which indicates that the tree string is the initial string repeating K times.The second line is the initial string S.
输出描述:
A single integer, the number of ways to remove trees mod 1000000007.

示例1

输入
1
100

输出
6

说明
Initially, the sequence is ‘100’. There are6 ways:
100
1_0
10_
_00
__0
_0_

示例2

输入
3
125390

输出
149796


题目大意:给你k个由0~9组成的连续字符串,可以删除任意位置和数量的字符,求有多少种删除的方案使得剩下的字符串转化为数字后能被5整除,答案对1e9+7取模。


解题思路:有k个字符串,稍微想下肯定是有关于k的规律,所以首先我们考虑一个字符串的情况,如果一个数字能被5整除,那么最后一位数字一定是0或5,所以我们在字符串最后一位留下0或5,然后对前面的字符就可以任意删除了,这样可以推出,在字符串第i位(我们是编号为0~strlen(str)-1)是0或5的删除方案为2^i种,然后回过头来考虑k,由前面推出的算法,我们得出在一个字符串中第i位的删除方案为:2^(i*1)+2^(i*2)...+2^(i*k),你会发现这是一个等比数列求和,所以我们对每一位的方案都求和即可,这个过程中就会运用到快速幂可除法取模运算了(因为等比求和有除法啊)。


不会快速幂的:快速幂运算
不会除法取模的:一看就懂的除法取模运算

AC代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<queue>
#include<map>
using namespace std;
const int INF = 1e9;
const int mod = 1e9+7;

long long a[100010], k;
char str[100010];

long long power(long long a, long long n)//一定要注意开longlong
{
    long long ans = 1;
    while(n > 0) {
        if(n&1) {
            ans *= a;
            ans %=  mod;
        }
        a *= a;
        a %= mod;
        n /= 2;
    }
    return ans%mod;
}

int main()
{
    while(~scanf("%lld", &k)) {
        scanf("%s", str);
        int cnt = 0;
        long long ans = 0;
        int len = strlen(str);
        for(int i = 0; i < len; i ++) {
            if(str[i] == '0' || str[i] == '5')
            a[cnt ++] = power(2, i); //我们用一个数组来记录首项
        }
        for(int i = 0; i < cnt; i ++) { //虽然很长,但其实就是一个除法取模公式
            ans += ((a[i]*(1-power(2, k*len)))%mod*power(1-power(2, len), mod-2))%mod;
            ans %= mod; //就是取模过程中不断要使用快速幂而已,自己打下草稿
        }
        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/i_believe_cwj/article/details/80147638
今日推荐