HDU5447 Good Numbers

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

网上好像只找到java的题解,写完就发一下c++代码咯,顺便纪念一下+存个int128板子

做法可以看tjz直播中的pdf:http://www.51nod.com/live/liveDescription.html#!liveId=5

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll MMH
#define ull unsigned long long
using namespace std;

inline ull M(ull x,ull MOD){while (x>=MOD)x-=MOD;return x;}
inline ull cheng(ull a,ull b,ull p){
    ull mmh=0;
    while (b){
        if (b&1) mmh=M(mmh+a,p);
        a=M(a+a,p);b>>=1;
    }
    return mmh;
}
char P_C[50],O_O[50];
char c[50]={"24408308522758834075998738377"};
char ss[36][50]={"18446744073709551616","36893488147419103232","73786976294838206464","147573952589676412928","295147905179352825856","590295810358705651712","1180591620717411303424","2361183241434822606848","4722366482869645213696","9444732965739290427392","18889465931478580854784","37778931862957161709568","75557863725914323419136","151115727451828646838272","302231454903657293676544","604462909807314587353088","1208925819614629174706176","2417851639229258349412352","4835703278458516698824704","9671406556917033397649408","19342813113834066795298816","38685626227668133590597632","77371252455336267181195264","154742504910672534362390528","309485009821345068724781056","618970019642690137449562112","1237940039285380274899124224","2475880078570760549798248448","4951760157141521099596496896","9903520314283042199192993792","19807040628566084398385987584","39614081257132168796771975168","79228162514264337593543950336","158456325028528675187087900672","316912650057057350374175801344","633825300114114700748351602688"};
inline bool ju(int i){
    int cl=strlen(c),sl=strlen(ss[i]);
    if (cl<sl) return 0;else
    if (cl==sl) for (register int j=0;j<cl;j++) if (c[j]<ss[i][j]) return 0;else if (c[j]>ss[i][j]) break;
    for (register int j=0;j<cl-sl;j++) c[j]-=48;
    for (register int j=0;j<sl;j++) c[cl-j-1]-=ss[i][sl-j-1];
    for (register int j=0;j<cl;j++)
    for (register int j=cl-1;j;j--)
    if (c[j]<0) c[j]+=10,c[j-1]--;
    for (i=0;c[i]==0&&i<cl;i++);
    if (i==cl) c[0]=‘0‘,c[1]=0;else for (register int j=i;j<=cl;j++) c[j-i]=c[j]+48;c[cl-i]=0;
    return 1;
}
inline unsigned long long change(){
    int cl=strlen(c);
    unsigned long long x=0;
    for (register int i=0;i<cl;i++) x*=10,x+=c[i]-48;
    return x;
}
inline void add(int x){
    int i;
    int cl=strlen(P_C),sl=strlen(ss[x]);
    for (i=0;i<sl;i++) O_O[i]=ss[x][sl-i-1]-48;
    for (i=0;i<cl;i++) O_O[cl-i-1]+=P_C[i]-48;
    if (sl>cl) cl=sl;
    for (i=0;i<cl;i++)
    if (O_O[i]>=10) O_O[i+1]+=O_O[i]/10,O_O[i]%=10,cl+=i==(cl-1);
    for (i=0;i<cl;i++) P_C[i]=O_O[cl-i-1]+48;P_C[cl]=0;
}
struct MMH{
    unsigned long long a,b;
    MMH(ull _a=0,ull _b=0):a(_a),b(_b){}
    void half(){
        b>>=1;
        if (a&1) b|=1ull<<63;
        a>>=1;
    }
    void two(){
        a<<=1;
        if (b&(1ull<<63)) a|=1;
        b<<=1;
    }
    void pr(){
        ull A=a,B=b;int s=0;
        memset(P_C,0,sizeof(P_C));
        memset(O_O,0,sizeof(O_O));
        while(B) O_O[s++]=B%10+48,B/=10;P_C[s]=0;
        for (register int i=0;i<s;i++) P_C[i]=O_O[s-i-1];
        for (register int i=0;i<=35;i++)
        if (A&(1ull<<i)) add(i);
        printf("%s ",P_C);
    }
};
MMH operator +(const MMH &x,const MMH &y){
    MMH z;
    z.a=x.a+y.a;z.b=x.b+y.b;if (z.b<x.b||z.b<y.b) z.a++;
    return z;
}
MMH operator +(const MMH &x,const int &y){
    MMH z=x;
    if ((z.b+y)<z.b) z.a++;z.b+=y;
    return z;
}
MMH operator -(const MMH &x,const MMH &y){
    MMH z;
    z.a=x.a-y.a;z.b=x.b-y.b;if (y.b>x.b) z.a--;
    return z;
}
MMH operator -(const MMH &x,const int &y){
    MMH z=x;
    if (z.b<y) z.a--;z.b-=y;
    return z;
}
MMH operator *(const MMH &x,const MMH &y){
    if (x.a){
        MMH z=x,mmh=MMH(0,0),u=y;
        while (u.a|u.b){
            if (u.b&1) mmh=mmh+z;
            z.two();u.half();
        }
        return mmh;
    }
    ull s=(1ull<<32)-1;
    ull a=(x.b>>32)*(y.b>>32),_b1=(x.b&s)*(y.b>>32),b=_b1+(x.b>>32)*(y.b&s),c=(x.b&s)*(y.b&s),d;
    a+=(b<_b1)*1ull<<32;
    d=c+((b&s)<<32);a+=d<c;a+=b>>32;
    return MMH(a,d);
}
bool operator <(const MMH &x,const MMH &y){return x.a==y.a?x.b<y.b:x.a<y.a;}
bool operator >(const MMH &x,const MMH &y){return x.a==y.a?x.b>y.b:x.a>y.a;}
bool operator !=(const MMH &x,const MMH &y){return x.a!=y.a||x.b!=y.b;}
bool operator ==(const MMH &x,const MMH &y){return x.a==y.a&&x.b==y.b;}
MMH operator %(const MMH &x,const MMH &y){
    if (x<y) return x;
    MMH z=y,c=x;
    while (!(z>c)) z.two();
    for(;;){
        z.half();
        if (!(c<z))c=c-z;
        if (z.a==y.a&&z.b==y.b) break;
    }
    return c;
}
MMH operator /(const MMH &x,const MMH &y){
    if (x<y) return MMH{0,0};
    MMH z=y,c=x,a=MMH{0,0};
    while (!(z>x)) z.two();
    for(;;){
        z.half();a.two();
        if (!(c<z))c=c-z,a.b|=1;
        if (z.a==y.a&&z.b==y.b) break;
    }
    return a;
}
int operator %(const MMH &x,const int &y){
    MMH z=x;
    z.a%=y;z.b%=y;
    z.a<<=32;z.a%=y;
    z.a<<=32;z.a%=y;

    z.b+=z.a;if (z.b>=y) z.b-=y;
    return z.b;
}
ull sqrt(MMH x){
    ull l=0,r=1e18,_mid;
    MMH mid;
    while (l<r){
        mid.a=0;mid.b=_mid=l+r>>1;
        mid=mid*mid;
        if (x==mid) return _mid;else if (x<mid) r=_mid-1;else if (x>mid) l=_mid+1;
    }
    return l;
}
ull sqrt3(MMH x){
    ull l=0,r=1e12,_mid;
    MMH mid=MMH(0,0);
    while (l<r){
        mid.a=0;mid.b=_mid=l+r>>1;
        mid=mid*mid*mid;
        if (x==mid) return _mid;else if (x<mid) r=_mid-1;else if (x>mid) l=_mid+1;
    }
    return l;
}
ull operator %(const MMH &x,const ull &y){
    MMH z=x;
    z.a%=y;z.b%=y;
    for (int i=0;i<64;i++) z.a<<=1,z.a%=y;

    z.b+=z.a;if (z.b>=y) z.b-=y;
    return z.b;
}
inline void read(MMH &n){
    scanf("%s",c);
    n.a=n.b=0;
    for (int i=35;i>=0;i--){
        n.a<<=1;
        if (ju(i)) n.a|=1;
    }
    n.b=change();
}
const int S=20;
const ull m_p[20]={2,5,7,61,97,37,101,13,11,997,2083,5807,7213,9907,10781,11897,14033,18013,43789,10009};
ll cheng(ll a,ll b,ll p){
    ll mmh;mmh=MMH{0,0};
    while (b.a||b.b){
        if (b.b&1) if (mmh=mmh+a,!(mmh<p)) mmh=mmh-p;
        b.half();a=a+a;if (!(a<p)) a=a-p;
    }
    return mmh;
}
ll mi(ll a,ll b,ll p){
    ll mmh;mmh={0,1};
    while (b.a||b.b){
        if (b.b&1ull) mmh=cheng(mmh,a,p);
        b.half();a=cheng(a,a,p);
    }
    return mmh;
}
bool prime_judge(ll n){
    if(n.b==2&&n.a==0) return 1;
    if((n.b<2&&n.a==0)||!(n.b&1)) return 0;
    for (register int i=0;i<S;i++)
    if (m_p[i]==n.b&&n.a==0) return 1;else if (mi(MMH{0,(n.a?m_p[i]:m_p[i]%n.b)},n-1,n)!=MMH{0,1}) return 0;
    return 1;
}
ll gcd(ll x,ll y){return (y.a==0&&y.b==0)?x:gcd(y,x%y);}
ll k1,k2,u;
#define MN 1000001
bool bo[MN];
ull mmh1,mmh2,T,p[MN],num=0,A;
inline void work(ll k,ull &mmh,ll u){
    if (u.a) return;
    ull s=u.b;
    if (s<1e8&&k==u*u*u) mmh*=3;else
    if (k==u*u||(s<=1e8&&k%(s*s)==0)) mmh*=2;else{
        if (k==u) return;
        k=k/u;
        u=MMH(0,sqrt(k));
        if (u*u==k) mmh<<=1;
    }
}
int main(){
    register int i,j;
    for (i=2;i<MN;i++){
        if (!bo[i]) p[++num]=i;
        for (j=1;j<=num&&i*p[j]<MN;j++)
        if (bo[i*p[j]]=1,i%p[j]==0) break;
    }
    scanf("%d",&T);
    while (T--){
        read(k1);read(k2);mmh1=mmh2=1;
        for (i=1;i<=num;i++)
        if (k1%p[i]==0){
            A=1;k1=k1/MMH{0,p[i]};
            while (k1%p[i]==0) A++,k1=k1/MMH{0,p[i]};
            mmh1=mmh1*A;
        }
        for (i=1;i<=num;i++)
        if (k2%p[i]==0){
            A=1;k2=k2/MMH{0,p[i]};
            while (k2%p[i]==0) A++,k2=k2/MMH{0,p[i]};
            mmh2=mmh2*A;
        }

        u=gcd(k1,k2);
        if (prime_judge(u)) work(k1,mmh1,u),work(k2,mmh2,u);else
        if (u!=MMH(0,1)){
            if (A=sqrt(u),u==MMH(0,A)*MMH(0,A)) mmh1*=(MMH(0,A)*u==k1)+2,mmh2*=(MMH(0,A)*u==k2)+2;else
            if (A=sqrt3(u),u==MMH(0,A)*MMH(0,A)*MMH(0,A)) mmh1*=3,mmh2*=3;
        }
        printf("%llu %llu\n",mmh1,mmh2);
    }
}

时间: 2024-08-12 17:05:33

HDU5447 Good Numbers的相关文章

LeetCode OJ - Sum Root to Leaf Numbers

这道题也很简单,只要把二叉树按照宽度优先的策略遍历一遍,就可以解决问题,采用递归方法越是简单. 下面是AC代码: 1 /** 2 * Sum Root to Leaf Numbers 3 * 采用递归的方法,宽度遍历 4 */ 5 int result=0; 6 public int sumNumbers(TreeNode root){ 7 8 bFSearch(root,0); 9 return result; 10 } 11 private void bFSearch(TreeNode ro

129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. For example, 1 / 2 3 T

421. Maximum XOR of Two Numbers in an Array

Given a non-empty array of numbers, a0, a1, a2, - , an-1, where 0 ≤ ai < 231. Find the maximum result of ai XOR aj, where 0 ≤ i, j < n. Could you do this in O(n) runtime? Example: Input: [3, 10, 5, 25, 2, 8] Output: 28 Explanation: The maximum resul

Humble Numbers(丑数) 超详解!

给定一个素数集合 S = { p[1],p[2],...,p[k] },大于 1 且素因子都属于 S 的数我们成为丑数(Humble Numbers or Ugly Numbers),记第 n 大的丑数为 h[n]. 算法 1: 一种最容易想到的方法当然就是从 2 开始一个一个的判断一个数是否为丑数.这种方法的复杂度约为 O( k * h[n]),铁定超时(如果你这样做而没有超时,请跟 tenshi 联系) 算法 2: 看来只有一个一个地主动生成丑数了 : 我最早做这题的时候,用的是一种比较烂的

【Scala】Scala之Numbers

一.前言 前面已经学习了Scala中的String,接着学习Scala的Numbers. 二.Numbers 在Scala中,所有的数字类型,如Byte,Char,Double,Float,Int,Long,Short都是对象,这七种数字类型继承AnyVal特质,这七种数字类型与其在Java中有相同的范围,而Unit和Boolean则被认为是非数字值类型,Boolean有false和true两个值,你可以获取到各个数字类型的最值. 复杂的数字和日期 如果需要更强大的数类,可以使用spire,sc

2、Add Two Numbers

1.Add Two Numbers--这是leedcode的第二题: You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input:

[LeetCode In C++] 2. Add Two Numbers

题目: You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input: (2 -> 4 -> 3) + (5 -> 6 -&

[LeetCode] Compare Version Numbers

Question: Compare two version numbers version1 and version2.If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0. You may assume that the version strings are non-empty and contain only digits and the . character.The 

LeetCode --- 2. Add Two Numbers

题目链接:Add Two Numbers You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input: (2 -> 4 -> 3