• 2019杭电多校训练(四)


    比赛链接:

    http://acm.hdu.edu.cn/search.php?field=problem&key=2019+Multi-University+Training+Contest+4&source=1&searchmode=source

    hdu6623

    题意:

    把一个数转化成质因数加指数连乘的形式,求最小指数

    分析:

    当时我们考虑先筛出$1e18^{frac{1}{4}}$的所有素数,复杂度大概在$2e8$左右,刚好被卡了

    其实筛到$1e18^{frac{1}{5}}$的情况也不是很复杂(当时以为四个因数太复杂了,没敢写)

    把小于$1e18^{frac{1}{5}}$的质因子去掉,剩下的最多有四个质因子

    如果M可以开四次根,那么M一定是qqqq的形式

    如果M可以开三次根,那么M一定是qqq的形式

    如果M可以开二次根,那么M一定是qq或者qqpp形式

    否则M一定存在一次幂

    ac代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn = 1e6 + 5;
    const ll mod = 1e9 + 7;
    int vis[maxn],prim[maxn],top;
    bool check(ll x,int y)//判断x能否开y次幂
    {
    
        ll st=1,en=pow(1e18,1.0/y)+1;
        while(st!=en){
            ll md=(st+en)/2;
            ll res=1;
            for(int i=1;i<=y;i++)res*=md;
            if(res>=x)en=md;
            else st=md+1;
        }
        ll res=1;
        for(int i=1;i<=y;i++)res*=st;
        if(res==x)return 1;
        else return 0;
    }
    
    int main()
    {
       // cout<<check(8,3)<<endl;
        for(int i=2;i<=4000;i++){
            if(vis[i]==0){
                prim[++top]=i;
                //cout<<i<<endl;
                for(int j=2*i;j<=4000;j+=i)
                    vis[j]=1;
            }
        }
        int T;
        scanf("%d",&T);
        while(T--){
            int ans=70;
            ll n;
            scanf("%lld",&n);
            for(int i=1;i<=top;i++){
                if(n%prim[i]==0){
                    int res=0;
                    while(n%prim[i]==0)n/=prim[i],res++;
                    ans=min(res,ans);
                    if(ans==1)break;
                }
            }
            if(n==1||ans==1){
                printf("%d
    ",ans);
                continue;
            }
            if(check(n,4))ans=min(ans,4);
            else if(check(n,3))ans=min(ans,3);
            else if(check(n,2))ans=min(ans,2);
            else ans=1;
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    hdu6621

    题意:

    给出$n$个数,和$m$次询问

    每次询问是一段区间中,所有数与$p$的差值的第$k$大

    分析:

    二分答案再主席树验证

    现在才真正理解主席树的含义,就是保存了$n$棵区间和的线段树

    既可以求第$k$大也可以求出某段区间数的数量

    ac代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=1e5+5;
    struct Tree
    {
         int L,R,num;
    }tree[maxn*25];
    int root[maxn];
    int cnt;
    void updata(int x,int &rt,int a,int b)
    {
         tree[cnt++]=tree[rt];
         rt=cnt-1;
         tree[rt].num++;
         if(a==b)return;
         int mid=(a+b)/2;
         if(x>=mid+1)
             updata(x,tree[rt].R,mid+1,b);
         else
             updata(x,tree[rt].L,a,mid);
    }
    int quer(int l,int r,int a,int b,int st,int en)//quer(root[l-1],root[r],r-l+1-mid,1,n)
    {
        if(a>en||b<st)return 0;
        if(a<=st&&b>=en)return tree[r].num-tree[l].num;
        int md=(st+en)/2;
        return quer(tree[l].L,tree[r].L,a,b,st,md)+quer(tree[l].R,tree[r].R,a,b,md+1,en);
    }
    int main()
    {
        int n,m,T;
        scanf("%d",&T);
        while(T--)
        {
            for(int i=0;i<maxn*25;i++)tree[i].num=0;
            scanf("%d %d",&n,&m);
            cnt=1;
            for(int i=1;i<=n;i++)
            {
                root[i]=root[i-1];
                int x;
                scanf("%d",&x);
                updata(x,root[i],1,1e6);
            }
    //        cout<<quer(root[1],r,1,1,1,1e6)<<endl;
            int ans=0;
            for(int i=1;i<=m;i++)
            {
                int l,r,p,k;
                scanf("%d %d %d %d",&l,&r,&p,&k);
                l^=ans,r^=ans,p^=ans,k^=ans;
                int st=0,en=1e6;
                while(st!=en){
                    int md=(st+en)/2;
                    if(quer(root[l-1],root[r],max(1,p-md),min(1000000,md+p),1,1e6)>=k)en=md;
                    else st=md+1;
                }
                ans=st;
                printf("%d
    ",st);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    面向对象三大特性?
    final finally finalize区别?
    LeetCode122-买卖股票的最佳时机2(贪心算法)
    LeetCode119-杨辉三角2(题目有Bug,动态规划)
    九度OJ 1051:数字阶梯求和 (大数运算)
    九度OJ 1050:完数 (数字特性)
    九度OJ 1049:字符串去特定字符 (基础题)
    九度OJ 1048:判断三角形类型 (基础题)
    九度OJ 1047:素数判定 (素数)
    九度OJ 1046:求最大值 (基础题)
  • 原文地址:https://www.cnblogs.com/carcar/p/11290006.html
Copyright © 2020-2023  润新知