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&&\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[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&&\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 3641 数论 二分求符合条件的最小值数学杂题,布布扣,bubuko.com

时间: 2024-10-09 08:41:30

hdu 3641 数论 二分求符合条件的最小值数学杂题的相关文章

一个自然数在1700和1800之间,且被5除余3,被7除余4,被11除余6,求符合条件的数

昨天晚上看了一道逻辑题:一个自然数在1700和1800之间,且被5除余3,被7除余4,被11除余6,求符合条件的数.题目后面写着,有人看了几分钟便给出了答案.我很好奇,此人是如何解答的. 我自己先琢磨了下,拿笔算了半天,最后一个巧合的情况下,得到了答案.此题的一个关键且明显的推论是:能被5除余3的数,肯定最后一位是3或者8.那么接下来怎么推呢?我从网上搜集了答案. 方案1: 这个数被5除余3,则此数个位数为3或8, 设这个数十位为x,则此数可表达为1703+10x,或1708+10x当此数为17

hdu 4961 数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=4961 先贴个O(nsqrtn)求1-n所有数的所有约数的代码: vector<int>divs[MAXN]; void caldivs() { for(int i=1;i<MAXN;i++) for(int j=i;j<MAXN;j+=i) divs[j].push_back(i); } 有了这个当时理下思路就可写了,但是重复数处理注意: 1.用一个数组vis[]  vis[i]=1表示i存在

hdu 1025 dp+二分求最长递增子序列

//dp[i],长度为i的递增子序列的最后一位的最小值 //对于这种处理得到的dp[i]必然是递增的 //对于第i个数a[i],只需要找到最小的大于它的位置pos, //由于是最小的大于a[i] ,pos - 1 的值必然小于a[i] //那么dp[pos] = a[i] ; #include<cstdio> #include<cstring> #include<iostream> using namespace std ; const int maxn = 50001

hdu Courses 1083 二分匹配 ,匈牙利算法。。水题

Courses Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4233    Accepted Submission(s): 2014 Problem Description Consider a group of N students and P courses. Each student visits zero, one or

hdu 4974 数学杂题/证明

题意模型:n个正数,每次可以做下面俩种操作之一: 1:取一个数减一. 2:取俩个数各减一. 都必需保证每次操作的数>0. 求使得所有数字为0的最少操作次数. 都说是简单题,网上还有不少错误解法(排序后扫一遍,每次取最大的俩个数减到0: 2 2 2 这样是4次,正解3次). 应该是每次取最大的俩个数,各减1. 若maxi>sum/2,则ans=max,每次操作都用那个max,和其他一个数,最后max没人找了,自己减. 若maxi<sum/2,则ans=(sum+1)/2.每次操作找俩个当前

hdu 4432 数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=4432 6分钟写的代码,一上午去调试,, 哎,一则题目没看懂就去写了,二则,哎,,恶心了,在坚持几天然后ACM退役,想当初一直想着regional拿奖,然后在保研的时候有个更漂亮的简历,卧槽,但是,其实喜欢的是静下心,把一块知识好好弄懂,看着自己一点点由不会到会,由不熟到熟练,而且在这个过程中总结一些思考问题的方法,能把这种思维应用于其他 但是----唉,急功近利式地学,老想着快,一没思路就去看题解,然后平均每

HDU - 1588 Gauss Fibonacci (矩阵快速幂+二分求等比数列和)

Description Without expecting, Angel replied quickly.She says: "I'v heard that you'r a very clever boy. So if you wanna me be your GF, you should solve the problem called GF~. " How good an opportunity that Gardon can not give up! The "Prob

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 (二分+分解质因子)

题目链接: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