链接:
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次的初始字符串。
第二行是初始串小号
。
输出描述:
单个整数,删除树的方法数量为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; }