题目大意:给定一个数,求这个数除了1有多少个约数;
题目解析:首先肯定不能暴力枚举,会超时,那么我们就想到把每个数表示成素数幂的乘积形式,所以我们这里先要把素数打表打出来,然后枚举每个素数出现的次数并把他们乘起来,最后把答案减1,因为1不可以,枚举素数的时候有个技巧很关键否则会超时:
如果当前prime[i]*prime[i]>n就要退出循环,如果此时n=1就不要管,如果n!=1则表示后面还有素数是n的因数,那我们考虑后面会有几个因数,如果有2个或者以上,那么他们的乘积肯定大于prime[i]的平方,矛盾,所以后面只可能有一个因数的几次幂,那我们再考虑会是几次幂呢,大于2的话也跟上述一样矛盾,所以幂指数只能为1,所以后面只有一个次数为1的因数了,所以答案只要乘以2即可;
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
bool vis[1000010];
int prime[1000010],cnt;
void getprime()
{
cnt=0;
int i,j;
for(i=2;i<=1000000;i++)
{
if(!vis[i])
prime[cnt++]=i;
for(j=2*i;j<=1000000;j+=i)
vis[j]=1;
}
}
ll fun(ll n)
{
ll ans=1;
int num,i;
for(i=0;i<cnt&&prime[i]*prime[i]<=n;i++)
{
if(n%prime[i]==0)
{
num=0;
while(n%prime[i]==0)
{
num++;
n/=prime[i];
}
ans*=(num+1);
}
}
if(n>1)
ans*=2;
return ans-1;
}
int main()
{
int cas,c;
ll n;
getprime();
scanf("%d",&cas);
for(c=1;c<=cas;c++)
{
scanf("%lld",&n);
if(n!=1)
printf("Case %d: %lld\n",c,fun(n));
else
printf("Case %d: 0\n",c);
}
return 0;
}