第十四届华中科技大学程序设计竞赛 B-beautiful tree cutting

链接: https
://www.nowcoder.com/acm/contest/106/B来源:牛客网

时间限制:C / C ++ 1秒,其他语言2秒
空间限制: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;
}


猜你喜欢

转载自blog.csdn.net/qq_40129237/article/details/80205549