HDU 3641 Treasure Hunting (素数拆分)

题意:有N个ai,bi,M=a1^b1*a2^b2*a3^b3…*an^bn ,求最小的 x 使得 x! % M ==0.

思路:把M分成多个素数相乘,num[i] 记录素数 i 的个数,然后二分找到x,若 x! 中所有 i 的个数满足>=num[i]

即为答案。

#include<cstdio>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<map>
#include<cmath>
#include<iostream>
#include <queue>
#include <stack>
#include<algorithm>
#include<set>
using namespace std;
#define INF 1e8
#define eps 1e-8
#define LL long long
#define maxn 100105
#define mod  1000000009  

int prime[25]={2,3,5,7,11,13,17,19,23,29,31,
	37,41,43,47,53,59,61,67,71,73,79,83,89,97};
__int64 num[105];
void Cal(__int64 a,__int64 b)//计算素数i的个数num[i]
{
	for(int i=0;i<25;i++)
	{
		while(a%prime[i]==0)
		{
			a/=prime[i];
			num[prime[i]]+=b;
		}
	}
}
__int64 find(int i,__int64 x)//计算x!中i的个数
{
	__int64 ans=0;
	while(x)
	{
		x/=i;
		ans+=x;
	}
	return ans;
}
bool ok(__int64 x)
{
	for(int i=0;i<25;i++)
	{
		if(num[prime[i]])
		{
			__int64 tmp=find(prime[i],x);
			if(tmp<num[prime[i]])
				return false;
		}
	}
	return true;
}
int n;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		__int64 a,b;
		scanf("%d",&n);
		memset(num,0,sizeof(num));
		for(int i=0;i<n;i++)
		{
			scanf("%I64d%I64d",&a,&b);
			Cal(a,b);
		}
		__int64 l=0,r=(__int64)1<<62,mid,ans;
		while(l<=r)
		{
			mid=(l+r)>>1;
			if(ok(mid))
			{
				ans=mid;
				r=mid-1;
			}
			else l=mid+1;
		}
		printf("%I64d\n",ans);
	}
	return 0;
}

HDU 3641 Treasure Hunting (素数拆分)

时间: 2024-11-06 19:26:10

HDU 3641 Treasure Hunting (素数拆分)的相关文章

HDU 3641 Treasure Hunting

用二分查找来找到一个X使得满足X!%M==0 M=a1^b1*a2^b2*a3^b3-*an^bn X!=1*2*3*4*5....*X; M可以化为其个个质因子的k次方的乘积 例如 2^3*3^2*4^5==2^13*3^2; X!则可以得到 例如 2的次方为 X! = 2^(X/2)*(1*2*3*4*5*6*7....*X/2)*other=(x/2)! *other; 继续计算知道x/2==1为止 得到次方数:再与输入的数比较 输入的ai,bi 计算并储存好个个质数的次方 #includ

HDU 3641 Treasure Hunting (二分+分解质因子)

题目链接:HDU 3641 Treasure Hunting 题意:求X!%M==0中最小的的X.其中M=a1^b1*a2^b2*a3^b3.... 思路:求余为0想到整除,即分母的因子构成的集合是分子的因子构成的集合的子集.因子又想到,任何一个整数都可以分解成若干个素数相乘. 注意:题目数据很大,查到答案时二分. AC代码: #include<stdio.h> #include<string.h> #define ll __int64 bool Prime[210]; ll nu

hdu 3641 Treasure Hunting 强大的二分

1 /** 2 大意:给定一组ai,bi . m = a1^b1 *a2^b2 * a3^ b3 * a4^b4*...*ai^bi 3 求最小的x!%m =0 4 思路: 将ai 质因子分解,若是x!%m=0 那么x! 质因子分解之后 质因子的个数一定大于等于m的个数.二分求解可得 5 注意: 二分时,需要将,上下限 设定好,low =0: high = 1ll<<60; 6 **/ 7 8 #include <iostream> 9 #include <cstring&g

HDU 3641 Treasure Hunting(阶乘素因子分解+二分)

题目链接:传送门 题意: 求最小的 ( x! ) = 0 mod (a1^b1*a2^b2...an^bn) 分析: 首先吧a1~an进行素因子分解,然后统计下每个质因子的指数,由于随着x的增大,质因子的个数是逐渐增加的 因此我们可以二分x,对x!进行素因子分解判断是否满足条件,然后求出最小的就可以了. 代码如下: #include <iostream> #include <cstring> #include <algorithm> #include <cstdi

HDU 3468 Treasure Hunting(BFS+网络流之最大流)

题目地址:HDU 3468 这道题的关键在于能想到用网络流.然后还要想到用bfs来标记最短路中的点. 首先标记方法是,对每一个集合点跑一次bfs,记录所有点到该点的最短距离.然后对于任意一对起始点来说,只要这个点到起点的最短距离+该点到终点的最短距离==起点到终点的最短距离,就说明这点在某条从起点到终点的最短路上. 然后以集合点建X集,宝物点建Y集构造二分图,将从某集合点出发的最短路中经过宝物点与该集合点连边.剩下的用二分匹配算法或最大流算法都可以.(为什么我的最大流比二分匹配跑的还要快....

HDU 3468 Treasure Hunting (最大流SAP)经典(看似广搜实则最大流)

Treasure Hunting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 1532    Accepted Submission(s): 400 Problem Description Do you like treasure hunting? Today, with one of his friend, iSea is on

hdu 3468 Treasure Hunting

二分图匹配 题意: ... 看了半天 我们可以从rally点出发到最近的rally点, 如果有treasure在这两个rally点的最短路径上, 我们可以拿走他. 思路也可以参见http://blog.csdn.net/wall_f/article/details/8990937 这种分析问题的思路太值得学习了.. 一开始没看懂题.. 在vj上找了个代码 (o(╯□╰)o.. 谴责一下自己..)然后写了一下注释.. 写完注释发现就那么回事 不想再敲一遍了..噗.. 1 /*Author :use

【网络流】 HDU 3468 Treasure Hunting

题意: A-Z&&a-z 表示 集结点 从A点出发经过 最短步数 走到下一个集结点(A的下一个集结点为B ,Z的下一个集结点为a) 的路上遇到金子(*)则可以捡走(一个点只能捡一次) 求从A点出发走遍所有的的集结点 最多能捡多少金子 思路:先对于第 i 个集结点用BFS求出 对于每个点从该集结点所需的步数  为D[ I ] [ t ] 对于任意一个金子若  两个相邻的集结点的最短步数=其到该金子的步数和 则建一条边(可以拿) 然后最大流求 #include <cstdio> #

Treasure Hunting (hdu 3468 二分匹配+bfs最短路径)

Treasure Hunting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 1509    Accepted Submission(s): 393 Problem Description Do you like treasure hunting? Today, with one of his friend, iSea is on