HDOJ-4344 Mark the Rope(数论)

来源:互联网 发布:淘宝米折报名入口 编辑:程序博客网 时间:2024/06/14 06:34

概括一下题意:将一个合数n的因数(不包括1和n)看做一个集合,求一个最大的子集使集合内所有元素都互质,并求出在上述条件下集合元素最大的和是多少。

解法:既然要保证子集内的元素互质,就要保证任意两个元素没有质因子。要元素数目做多,则每个元素包含的质因子数目最少,即为1。

做法也就出来了,对n进行拆分质因数,表示成 n=(a1^p1)*(a2^p2)*(a3^p3)*......*(ak^pk),则子集大小就是k,子集所有元素的最大的和就是(a1^p1)+(a2^p2)+(a3^p3)+......+(ak^pk)。当然,有一种特殊情况,就是n只有一种质因数,n=a^p,例如16,9等等,因为n不在大的集合之内,所以sum=a^(p-1)

现在转化为了大数快速分解质因数的问题,可以使用神奇的“pollard-rho”算法

传送门:http://www.cnblogs.com/jackiesteed/articles/2019910.html

在pollard-rho算法中用到了Miller-Rabin素数检验

传送门:http://www.matrix67.com/blog/archives/234

如果感觉自己很难理解,还是老老实实套模板吧:

(kuangbin模板)


#include <ctime>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;/*Miller_Rabin 算法判断是否为素数*/const int S=8;//ret=(a*b)%c;LL mult_mod(LL a,LL b,LL c){a %= c;b %= c;LL ret=0;LL tmp=a;while(b){if(b&1){ret+=tmp;if(ret>c) ret-=c;}tmp<<=1;if(tmp>c) tmp-=c;b>>=1;}return ret;}//res=x^n %mod;LL pow_mod(LL x,LL n,LL mod){    LL t,res;    res=1;t=x;    while(n)    {        if(n&1)res=mult_mod(res,t,mod);        n>>=1;        t=mult_mod(t,t,mod);    }    return res;}//是合数返回1,不一定是合数返回0bool check(LL a, LL n, LL x, LL t){int i;LL ret=pow_mod(a,x,n);LL last=ret;for(i=1;i<=t;i++){ret=mult_mod(ret,ret,n);if(ret==1 && last!=1 && last!=n-1) return 1;last=ret;}if(ret!=1)return 1;elsereturn 0;}//很可能是素数返回1,一定不是素数返回0bool Miller_Rabin(LL n){int i;if (n<2)      return 0;if (n==2)     return 1;if ((n&1)==0) return 0;LL x=n-1;LL t=0;while((x&1)==0){x>>=1;t++;}srand(time(NULL));for(i=0;i<S;i++){LL a=rand()%(n-1)+1;if(check(a,n,x,t))return 0;}return 1;}/*pollard_rho算法进行质因数分解*/LL factor[1000];int tol;//质因数个数LL gcd(LL a,LL b){LL t;while(b){t=a;a=b;b=t%b;}if(a>=0) return a;else return -a;}LL pollard_rho(LL x,LL c){LL i=1,k=2;srand(time(NULL));LL x0=rand()%(x-1)+1;LL y=x0;while(1){i++;x0=(mult_mod(x0,x0,x)+c)%x;LL d=gcd(y-x0,x);if(d!=1 && d!=x) return d;if(y==x0) return x;if(i==k){y=x0;k+=k;}}}void findfac(LL n,int k){if(n==1) return ;if(Miller_Rabin(n)){factor[tol++]=n;return ;}LL p=n;int c=k;while(p>=n)p=pollard_rho(p,c--);findfac(p,k);findfac(n/p,k);}void work(){int i;LL n,ans,tmp,cnt;scanf("%I64d",&n);tol=0;findfac(n,107);sort(factor,factor+tol);ans=0;tmp=factor[0];cnt=1;for(i=1;i<tol;i++){if(factor[i]!=factor[i-1]){cnt++;ans+=tmp;tmp=factor[i];}else{tmp*=factor[i];}}ans+=tmp;if(cnt==1) ans/=factor[0];printf("%I64d %I64d\n",cnt,ans);}int main(){int T;scanf("%d",&T);while(T--)work();return 0;}


0 0
原创粉丝点击