lightoj 1341 Aladdin and the Flying Carpet(算术基本定理)题解
题意:给一个矩形(非正方形)面积a和最小边长b,要求边长均大于b,求这样的矩形有几个
思路:先用到了之前学的质因数分解,还有一个新的公式:
然后我们可以先算出a的所有约数,因为只算约数个数面积重复,所以要/2;然后暴力出<b的所有约数减去。
技巧:1.用save[i]*save[i]<=temp剪枝 2.要注意判断出循环的ans是否大于1,如果大于1则表示还有一个素数没除尽,*2
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<queue>
#include<cmath>
//#include<map>
#include<string>
#include<iostream>
#include<algorithm>
#define INF 0x3f3f3f3f
const int N=1005005;
const int MOD=1000;
using namespace std;
int prime[N],save[N],pnum; //save存储了素数
void getprime(){
pnum=0;
memset(prime,0,sizeof(prime));
prime[0]=prime[1]=1;
for(long long i=2;i<N;i++){
if(!prime[i]){
save[pnum++]=i;
for(long long j=i*i;j<N;j+=i){
prime[j]=1;
}
}
}
}
int main(){
long long T,t,i,j,num;
long long a,b,ans,temp;
getprime();
scanf("%d",&T);
for(t=1;t<=T;t++){
scanf("%lld%lld",&a,&b);
if(b>a/b){
printf("Case %d: 0\n",t);
continue;
}
ans=1;temp=a;
for(i=0;i<pnum && save[i]*save[i]<=temp;i++){
if(temp%save[i]==0){
num=0;
while(temp%save[i]==0){
num++;
temp/=save[i];
}
ans*=(num+1);
}
if(temp<save[i]) break;
}
if(temp>1) ans*=2; //这里一开始没想到
ans/=2;
for(i=1;i<b;i++){
if(a%i==0) ans--;
}
printf("Case %d: %lld\n",t,ans);
}
return 0;
}