LightOJ1341-Aladdin and the Flying Carpet 【唯一分解定理】
Aladdin and the Flying Carpet
题目
给一对数字 a,b ,a是一个长方形的面积,问有多少种整数的边的组合可以组成面积为a的长方形,要求最短的边不得小于b。一共询问T<=4000次
分析
首先我们把面积进行质因数分解,得
所以其因子个数就是
此题目的就是让选出合法的因子,我们可以发现x*y = N
,选x选y都一样,x!=y
,所以本题答案就是 res = cnt/2-小于b的因子
,因为本题只需要长方形,所以cnt/2
,会自动把x*x = N
这种情况去掉。
关于为何打一个小于1e6的质数表就够了
因为我们是要用质数表来选质因数分解,假如N中有且仅有一个因子x且大于1e6,他会在质因数分解迭代完之后自身变成x。代码中这句就是考虑了这种情况if(x>1) res*=2;
。所以打一个1e6的质数表就够了。
AC代码
#include <iostream> #include <algorithm> #include <cmath> #include <stdio.h> using namespace std; typedef long long ll; const int maxn = 1e6+10; ll T,N,b; ll P[maxn],tail; bool vis[maxn]; void init(){ int len = (int)sqrt(maxn)+1; for(int i = 2;i<=len;i++){ if(!vis[i]){ for(ll j = i*i;j<maxn;j+=i){ vis[j] = true; } } } for(int i =2;i<maxn;i++){ if(!vis[i]) P[tail++] = i; } } ll get_div(ll x){ ll res = 1; for(int i = 0;i<tail && P[i]*P[i]<=x;i++){ //因为P[i]是从小到大遍历的,是所以当P[i]*P[i]>x时,此时他就已经没有除自身之外其他质因数了 if(x%P[i] == 0){ ll cnt = 0; while(x%P[i] == 0){ cnt++; x/=P[i]; } res *= cnt+1; } } if(x>1) res*=2; return res; } int main(){ init(); cin>>T; int kase = 0; while(T--){ scanf("%lld %lld",&N,&b); if(b*b>N){ printf("Case %d: %d\n",++kase,0); }else{ ll cnt = 0; for(int i = 1;i<b;i++) if(N%i == 0) cnt++; ll res = get_div(N); res/=2; printf("Case %d: %lld\n",++kase,res-cnt); } } return 0; }