一群小青蛙呱蹦呱蹦呱

这篇博客介绍了如何解决一个关于青蛙跳跃路径和数列的数学问题。牛牛放出了许多青蛙,每只青蛙沿着等比数列的路径跳跃并吃掉格子里的数。问题求解所有未被吃掉的数的最小公倍数(LCM)。博主通过分析发现,只需考虑每个质因子的最大指数,然后计算这些最大指数的乘积即可得到答案。代码中使用了线性筛法找出质数,并计算了每个质因子的最大幂次,最后计算了模10^9+7的LCM。
摘要由CSDN通过智能技术生成

题目描述:

有n个格子,每个格子里有一个数,1,2,3,4…n

牛牛放出无穷只青蛙。

第一只青蛙的路线是:1->2->4->8->16->…

第二只青蛙的路线是:1->3->9->27->81->…

第三只青蛙的路线是:1->5->25->125…

第四只青蛙的路线是:1->7->49…

。。。。。。

用数学语言描述,第 i只青蛙的路线是首项为1,公比为p(i)的等比数列,其中p(i)代表第个素数。

当青蛙跳到一个格子上,如果这个格子上面有一个数,青蛙就会把这个数吃掉。

牛牛想知道,所有没有被吃掉的数的lcm(最小公倍数 ,Least common multiple)是多少?

由于这个lcm可能非常大,请输出它对109 + 7取模的值。

输入描述:

一个整数n

1 <= n <= 1.6 * 108

输出描述:

如果所有数都被吃掉了,请输出一个字符串"empty"

否则输出所有没有被吃掉的数的lcm,对模109 + 7

思路:

2可以划掉 2 k 2^{k} 2k,3可以划掉 3 k 3^{k} 3k,5可以划掉 k ^{k} k
那么没有划掉的数字有它具有2个以上的质因子。
然而我们求lcm。
只需要求每个质因子的最大幂数的乘积就是结果。

所以对于每个质因子,我们只需要求出他的最高项就ok了。
对于2这个质因子,他所能达到的最大数就是: 3 ∗ 2 k < = n 3*2^k<=n 32k<=n
对于其他质因子p,它所能达到的最大数就是: 2 ∗ p k < = n 2 * p^k<=n 2pk<=n

因为至少含有2个因子,所以p的最大值会小于等于 n / 2 n/2 n/2
至于选择素数可以直接线性筛。

详细:https://aspire-zero.github.io/2021/03/01/yi-qun-xiao-qing-wa-gu-beng-gu-beng-gu/

代码:
#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<sstream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define inf 0x3f3f3f3f
#include<cstring>
#include<cstdio>
#define  ll long long
#define PI acos(-1)
#define mset(s, _) memset(s, _, sizeof(s))
//#define lo
using namespace std;
void coutx(double q, int x)
{
	//cout.setf(ios::fixed);
	//cout.unsetf(ios::fixed);
	cout << fixed << setprecision(x) << q << endl;
	return ;
}
inline ll ksc(ll x, ll y, ll mod)//快速乘
{
    return ( x * y - (ll) ( (long double) x / mod*y )*mod + mod ) % mod;
}
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b)
{
    return a/gcd(a,b)*b;
}
const int mod1 = 1e9 + 7;
const int N = 8e7+7;
bool isprime[N];
ll vis[N];
int sieve(int n)//线性筛
{
	int cnt = 0;
	isprime[0] = isprime[1] = true;
	for(int i = 2; i <= n; i ++)
	{
		if(!isprime[i])		vis[ ++ cnt] = i;
		for(int j = 1; j <= cnt && i * vis[j] <= n; j ++)
		{
			isprime[i * vis[j]] = 1;
			if(i % vis[j] == 0)
				break;
		}	
	}
	return cnt;
}
int log(int n, int m)//求log
{
	ll res = 0;
	ll t = 1;
	while(t <= m)
	{
		t *= n;
		res ++;
	}
	return res - 1;
}
ll poww(ll a, ll b)//快速幂
{
	ll ans = 1;
	while(b)
	{
		if(b & 1) 
			ans = ksc(ans, a, mod1) % mod1;
		a = ksc(a, a, mod1) % mod1;
		a %= mod1;
		b >>= 1;
		ans %= mod1;
	}
	return ans % mod1;
 } 
int main()
{
	#ifdef lo
	 freopen("data.in","r",stdin);
	 freopen("data.out","w",stdout);
	#endif
	srand((unsigned int)time(0));
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n, cnt;
	ll ans;
	cin >> n;
	if(n <= 5)
	{
		cout << "empty";
		return 0;
	}
	cnt = sieve(n / 2);
	ans = poww(2, log(2, n / 3));
	for(int i = 2; i <= cnt; i ++)
	{
		ans = (ans % mod1) * poww(vis[i], log(vis[i], n / 2));
		ans %= mod1;
	}
	cout << ans % mod1;
	return 0;
 }


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值