2019杭电多校第四场

AND Minimum Spanning Tree

求一个完全图的最小生成树,定义边(u,v)的权值为u&v。
n为1e6,暴力肯定求不了,找规律:
发现任何偶数&1的时候都为0,奇数的情况发现只要和相反数按位与就为0,但是要满足字典序最小,所以只要保留最低位的1即可。

Minimal Power of Prime

1s,50000次询问,1e18分解质因数,求最小的因数的幂。
关注题目,因为只要求最小的幂,并没有要求全部分解出来。
经过观察,给出的数的素因子越大,其幂越小。先用N1/5N^{1/5}以内的素数试着将NN分解,不妨将剩下的部分记为MM,可知MM的因子一定大于N1/5N^{1/5}。想要求幂最小的情况,不妨先考虑幂最大的情况,发现当M=PaM=P^a时,有最多的幂。又M<1e18,故a&lt;=4a&lt;=4。因此MM可以分解为PP2P3P4P2Q2P、P^2、P^3、P^4、P^2*Q^2四种情况,将之前分解的最小值与出现这几种情况之一时的值比较一下即可。
贴上队友的代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
//#include<time.h>
#define ll long long
using namespace std;
ll pri[1020]={2,3,5,7,11,...,8093,8101,8111};
ll cnt=1000;
ll T,n;
int main(){
    //clock_t start = clock();
    //srand(time(NULL));
    scanf("%lld",&T);
    while(T--){
        scanf("%lld",&n);
        ll _n=n;
        ll mn=100,tmp;
        for(ll i=1;i<=600;i++){
            tmp=0;
            while(!(_n%pri[i])){
                tmp++;
                _n/=pri[i];
            }
            if(tmp){
                mn=min(mn,tmp);
                if(mn==1) break;
            }
        }
        if(mn==1||_n==1){
            printf("%lld\n",mn);
            continue;
        }
        ll s4=pow(_n+0.3,1.0/4)+0.3;
        ll s3=pow(_n+0.3,1.0/3)+0.3;
        ll s2=sqrt(_n)+0.3;
        if(s4*s4*s4*s4==_n){
            mn=min(mn,4);
        }
        else if(s2*s2==_n){
            mn=min(mn,2);
        }
        else if(s3*s3*s3==_n){
            mn=min(mn,3);
        }
        else{
            mn=min(mn,1);
        }
        printf("%lld\n",mn);
    }
    //clock_t ends = clock();
    //cout <<"Running Time : "<<(double)(ends - start)/ CLOCKS_PER_SEC << endl;
    return 0;
}
posted @ 2019-08-01 23:34  Mr.doublerun  阅读(6)  评论(0)    收藏  举报