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
",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
",t,ans);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/KirinSB/p/9409122.html