整数拆分问题(1)

来源:互联网 发布:心动网络所有游戏 编辑:程序博客网 时间:2024/05/21 01:56


我们一起来看看这个问题,说实话,当时一看到这题的时候我怕了,不过想通后那叫一个爽啊!得意

题意:给你一个N,求满足1/X+1/Y=1/N的X,Y种类数


当你看到这题的时候,你会怎么做呢?

当时我看到第一反应就是先化简,因为1/X这个数肯定是比1小的小数,这个精度问题是个大问题,而且两个小数相加也不会完全等于那个小数。所以,想办法划成整数关系式。

两边同乘XY,得  Y+X=XY/N

转换,得        N=XY/(X+Y)

然后直接求吗?不不不,N是个整数,难道你就能保证右边除出来是整数吗?!

然后,绞尽脑汁,沉思,深呼吸,学下一休哥,忽然想到了!

你可以保证,当两个分数相加要等于一个分数时,两个分数的分母肯定都大于这个分数的分母,也就是X,Y>N

我们可以假设,X=N+u,Y=N+v, 其中u,v肯定都是大于0的整数

然后代入,简化出来,不可思议,N^2=uv

而一个整数N都是可以拆成 N=p1^a1 * p2^a2 *……*pn^an 的形式

此时N拆成两个数相乘的形式的种类个数是(a1+1)*(a2+1)*……*(an+1) 【不细讲了,你可以自己去写几个找找规律】

那么N^2=p1^2a1 * p2^2a2 *……*pn^2an

此时,种类数即为(2a1+1)*(2a2+1)*……*(2an+1)  

这个问题就迎刃而解了,接下来就是求底和幂的事情了。

需要特别注意的是当N<2时,是无法整数拆分的,也就是种类数为0


#include <iostream> #include <cmath> using namespace std; #define MAXI 20 struct yinshu {     int di;     int mi; }; struct Div {     int xiangshu;     int xdi[MAXI];     int xmi[MAXI]; }; Div getpN(int m); void vout(Div pN); yinshu getOne(int yin,int& m); int main() {     int ncase,n,i;     cin>>ncase;     Div pN;     while(ncase--)     {         cin>>n;         pN=getpN(n);         vout(pN);     }     return 0; } Div getpN(int m) {     int i,j;     Div pans;     yinshu x;     if(m<2)     {         pans.xdi[0]=1;         pans.xmi[0]=0;         pans.xiangshu=0;         return pans;     }     int uplimit=(int)sqrt(m*1.0);     i=2;     j=0;     while(i<=uplimit)     {         if(m%i==0)         {             x=getOne(i,m);             pans.xdi[j]=x.di;             pans.xmi[j]=x.mi;             j++;             uplimit=(int)sqrt(1.0*m);         }         i++;     }     if(m>1)     {         pans.xdi[j]=m;         pans.xmi[j]=1;         j++;     }     pans.xiangshu=j;     return pans; } void vout(Div pN) {     int i;     int ans=1;     for(i=0;i<pN.xiangshu;i++)     {         ans*=(pN.xmi[i]*2+1);     }     cout<<ans<<endl; } yinshu getOne(int yin,int& m) {     yinshu x;     x.di=yin;     x.mi=0;     while(m%yin==0)     {         x.mi++;         m/=yin;     }     return x; } 



0 0
原创粉丝点击