链接:
https
://www.nowcoder.com/acm/contest/106/B来源:牛客网
://www.nowcoder.com/acm/contest/106/B来源:牛客网
时间限制:C / C ++ 1秒,其他语言2秒
空间限制:C / C ++ 32768K,其他语言65536K
64bit IO格式:%lld
空间限制:C / C ++ 32768K,其他语言65536K
64bit IO格式:%lld
题目描述
普遍认为华中校园里有无数树木。
有一天,小明走在一条直路上,看见右边有许多树木排队。用从0到9的非负整数表示的每棵树的高度可以形成一个树串。发现树字符串可以表示为重复ķ次的初始字符串,这是非常令人惊讶的。现在他想删除一些树木,使树的其余部分看起来很漂亮。当且仅当它所表示的整数可被5整除时,字符串才是美丽的。现在他想知道他可以做多少种方法。
请注意,当我们将字符串转换为整数时,我们忽略前导零。例如,字符串“00055”将被视为55并且请注意,如果删除的树不同,则认为两种方式是不同的。结果可能非常大,因此打印答案(mod 1000000007)就足够了。此外,小明不能砍倒所有的树木。
输入描述:
第一行包含一个整数K
,表示树字符串是重复K次的初始字符串。
![](https://i-blog.csdnimg.cn/blog_migrate/d18647eaa1185866f8e723e330f89737.png)
第二行是初始串小号
。
![](https://i-blog.csdnimg.cn/blog_migrate/78e87e38b5bbccbc1657af36f96c4b44.png)
输出描述:
单个整数,删除树的方法数量为1000000007。
解题思路:https ://blog.csdn.net/I_believe_CWJ/article/details/80147638
主要用到的知识点:快速幂算法以及除法模运算
核心思想:能被5整除的数的特点是最后一位是0或5,我们先从k=1考虑,当串s中s[i]是0或5的数,我们就可以把s[i]前面的所有的s[j](j<i)都随意删除,即删除的情况为2^i,当k不为1的时候,我们从串s中可以得到所有的为0或5的树的位置,如果s[i]是0或5,那么(i+len),(i+2*len)....一直到(i+k*len)都是0或5有效存在的,所以这时候的删除方案有2^i+2^(i+len)+2^(i+2*len)...+2^(i+k*len)。需要注意的是,这里等比数列的计算公式为a1*(1-q^n)/(1-q)。这里的n是k。
AC代码:
#include<iostream>
#include<math.h>
#include<string>
#include<algorithm>
using namespace std;
const long long int maxn = 1e5 + 5;
typedef long long int LL;
int k;
LL mod = 1e9 + 7;
char s[maxn];
int a[maxn];
LL fun(LL a, LL b)
{
LL ans = 1;
while (a&&b)
{
if (b & 1)
{
ans *= a;
ans %= mod;
}
a *= a;
a %= mod;
b >>= 1;
}
return ans;
}
int main()
{
LL ans = 0;
cin >> k;
cin >> s;
int t = 0;
int length = strlen(s);
for (int i = 0; i < length; i++)
{
if (s[i] == '0' || s[i] == '5')
{
a[t++] = fun(2, i);
}
}
for (int i = 0; i < t; i++)
{
ans += (a[i] * (fun(2, length*k) - 1)) % mod*fun((fun(2, length) - 1), mod - 2) % mod;
ans %= mod;
}
cout << ans << endl;
return 0;
}