zoukankan      html  css  js  c++  java
  • hdu 3641 数论 二分求符合条件的最小值数学杂题

    http://acm.hdu.edu.cn/showproblem.php?pid=3641

    学到:
    1、二分求符合条件的最小值

    /*====================================================
        二分查找符合条件的最小值
    ======================================================*/
    ll solve()
    {
         __int64 low = 0, high = INF, mid ;
        while(low <= high){
            mid = (low + high) >> 1;
    //         printf("%d&&
    ",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[N]; 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&& ",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 ",solve()); } return 0; }



  • 相关阅读:
    Python正课48 —— 匿名函数及其应用
    Python正课47 —— 面向过程编程思想
    Python正课46 —— 二分法
    Python正课45 —— 函数的递归调用
    Python正课44 —— 生成式
    Python正课43 —— 三元表达式
    SQL数据库操作命令大全
    css 高度写死 下滚动时ios 滚动不协调处理
    记录:js删除数组中某一项或几项的几种方法
    本次存储存数组对象
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7255555.html
Copyright © 2011-2022 走看看