hdu 3641 数论 二分求符合条件的最小值数学杂题
2017-07-29 12:39
513 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3641
学到:
1、二分求符合条件的最小值
2、求x!中prime[i]的个数
牛逼的代码。解释例如以下:
比方x=16,prm[i]=2。一般的思路是2,4,6,8,10,12,14,16 算出这几个数的因子2的个数和,由于4,8,16等不止包括一个因子,所以不是一重循环就能够搞的
这个代码在O(logn)搞了 方法是 k*=prm[i] 比方包括2的平方这个因子的数是4,8,16,那么第一次k=2的时候已经加过一次1,当k*=2 即k==4的时候。又加了一个1,也就相当于考虑上2的二次, 不错的代码
学到:
1、二分求符合条件的最小值
/*==================================================== 二分查找符合条件的最小值 ======================================================*/ ll solve() { __int64 low = 0, high = INF, mid ; while(low <= high){ mid = (low + high) >> 1; // printf("%d&&\n",mid); if(C(mid)) high = mid - 1; else low = mid + 1; } return low; }
2、求x!中prime[i]的个数
for(ll k=prm[i];k<=x;k*=prm[i]) { sum+=x/k; /// if(sum>=num[prm[i]])break; }
牛逼的代码。解释例如以下:
比方x=16,prm[i]=2。一般的思路是2,4,6,8,10,12,14,16 算出这几个数的因子2的个数和,由于4,8,16等不止包括一个因子,所以不是一重循环就能够搞的
这个代码在O(logn)搞了 方法是 k*=prm[i] 比方包括2的平方这个因子的数是4,8,16,那么第一次k=2的时候已经加过一次1,当k*=2 即k==4的时候。又加了一个1,也就相当于考虑上2的二次, 不错的代码
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <iomanip> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; #define ls(rt) rt*2 #define rs(rt) rt*2+1 #define ll long long #define ull unsigned long long #define rep(i,s,e) for(int i=s;i<e;i++) #define repe(i,s,e) for(int i=s;i<=e;i++) #define CL(a,b) memset(a,b,sizeof(a)) #define IN(s) freopen(s,"r",stdin) #define OUT(s) freopen(s,"w",stdout) const ll ll_INF = ((ull)(-1))>>1; const double EPS = 1e-8; const ll INF = ll_INF/2;//99999999999999999999;///ll_INF;// const int MAXN =110; const int N = 110; const int M = N; int prmcnt; bool is ; int prm[M]; int getprm(int n){ int i, j, k = 0; int s, e = (int)(sqrt(0.0 + n) + 1); memset(is, 1, sizeof(is)); prm[k++] = 2; is[0] = is[1] = 0; for(i = 4; i < n; i += 2) is[i] = 0; for(i = 3; i < e; i += 2) if(is[i]) { prm[k++] = i; for(s = i * 2, j = i * i; j < n; j += s) is[j] = 0; // 由于j是奇数,所以+奇数i后是偶数,不必处理! } for( ; i < n; i += 2) if(is[i]) prm[k++] = i; return k; // 返回素数的个数 } ll a[MAXN],b[MAXN]; ll num[MAXN]; ll getnum(ll t, ll pm) { ll ret=0; while(t%pm == 0) { ret++; t/=pm; } return ret; } bool C(ll x) { ll sum=0; for(int i=0;i<prmcnt;i++) if(num[prm[i]])/// { sum=0; for(ll k=prm[i];k<=x;k*=prm[i]) { sum+=x/k; /// if(sum>=num[prm[i]])break; } if(sum<num[prm[i]])return 0; } return 1; } /*ll solve() { ll d=0,up=INF,mid; while(up>d+1) { mid=(d+up)/2; if(C(mid))up=mid; else d=mid; } return up; }*/ ll solve() { __int64 low = 0, high = INF, mid ; while(low <= high){ mid = (low + high) >> 1; // printf("%d&&\n",mid); if(C(mid)) high = mid - 1; else low = mid + 1; } return low; } int main() { //IN("hdu3641.txt"); prmcnt=getprm(105); int ncase; int n; scanf("%d",&ncase); while(ncase--) { CL(num,0); scanf("%d",&n); for(int i=0;i<n;i++) scanf("%I64d%I64d",&a[i],&b[i]); for(int i=0;i<n;i++) { for(int j=0;j<prmcnt;j++) { if(a[i]%prm[j] == 0) { num[prm[j]]+=getnum(a[i],prm[j])*b[i]; } } } printf("%I64d\n",solve()); } return 0; }
相关文章推荐
- HDU 4766 模拟退火(最小圆覆盖) + 二分
- HDU 4279 Number (数论,数学)
- HDU 3641 Treasure Hunting(阶乘素因子分解+二分)
- HDU - 5288-OO’s Sequence-数学+分类再二分+枚举+contribution costing
- HDU 1792 A New Change Problem(数学规律题,数论知识)
- HDU 4606 Occupy Cities (计算几何+最短路+二分+最小路径覆盖)
- HDU 1597 二分+数学
- hdu 3641 神二分 有木有
- HDU 6216 A Cubic number and A Cubic Number(数论+二分)
- 数学_二分幂取模(HDU_1097)
- (hdu step 4.2.4)A strange lift(求从起点到终点的最小步数,限制条件是:在一维的情况下)
- HDU 5439 Aggregated Counting(数论+二分)
- 算法:数的每个位数相乘等于给出的数,并且这个数是符合条件的数中最小的数
- HDU ~ 4430 ~ Yukari's Birthday(二分or数学)
- hdu 5109 Alexandra and A*B Problem(取模,枚举,数学数论)
- HDU 1588(数论,构造二分矩阵+求幂运算+二分求和)
- hdu 1054 Strategic Game(模板) 最大二分匹配,最小点覆盖 匈牙利算法
- [WIKIOI 1250]Fibonacci数列(数论+数学+矩阵乘法+二分快速幂)
- HDU 4390 组合数学&数论
- hdu_2446_Shell Pyramid(数学,二分)