博客版权已保护:转载请注明出处,谢谢。

数论专题第三题 :C - Aladdin and the Flying Carpet

可能还是太菜了,最近每写一道题都会显得十分吃力,不过令人欣慰的是还可以从中学到不少的东西。

题目的大概意思:给出面积啊a,还有最短的边b,求出能够组成矩形一共有多少个组合。
samole input:

10 2
12 2
sample output:

1       (10一共有两对因数,2,5还有1,10);

2

分析:题目的意思很明显就是要求出a的符合条件的因数的对数找出来,那么涉及到数的因数,就应该想到“算术基本定理”,而算法基本定理又要有素数作为铺垫,所以筛选素数又要用到”欧拉函数筛选法“

思路:先用“算术基本定理”算出a总体一共有多少个因数,在除以2来求对数,之后暴力求出1到b有多少限制的对数,两者相减便是答案。

注意事项:由于a给出的范围是10的12次方,所以素数筛选只需要筛选到10的6次方就可以了(m*m=a,过了m之后便会重复)。

第二个注意的地方也是题目最为关键的地方之一:代码如下:

if(a/b < b)      //意思就是当b的限制达到a的算术平方根的时候,那么将不会在存在任何一个满足题目的组合,那么就可以直接输出结果,并且continue循环执行下一个;
        {
           printf("Case %d: %lld\n",i,0);
            continue;
        }

总体的代码走一走:

#include<cstdio>
#include<iostream>
#include<cstring>
#define Max 1000005
#include<cmath>
using namespace std;

typedef long long int ll;
bool vis[Max];
int p[Max],p_num=0;
void ola()
{
    memset(vis,false,sizeof(vis));
    memset(p,0,sizeof(p));
    for(int i=2;i<Max;i++)
    {
        if(!vis[i])
            p[p_num++]=i;
        for(int j=0;j<p_num;j++)
        {
            if(i*p[j]>Max)
                break;
            vis[i*p[j]]=true;
            if(i%p[j]==0)
                break;
        }
    }
}

ll Ans(ll n)
{
    ll sum =1;
    for(int i=0;i<p_num && p[i]<=n;i++)
    {
        if(n%p[i]==0)
        {
            int cnt=0;
            while(n%p[i]==0)
            {
                n=n/p[i];
                cnt++;
            }
            sum=sum*(cnt+1);
        }
    }
    if(n>1)
        sum=sum*2;
    return sum;
}

int main()
{
    ola();
    int T;
    ll a,b;
    scanf("%d",&T);
    for(int i=1;i<=T;i++)
    {
        scanf("%lld %lld",&a,&b);

        if(a/b < b)
        {
           printf("Case %d: %lld\n",i,0);
            continue;
        }
        ll cnt = Ans(a)/2;
        for(int j=1;j<b;j++)
        {
            if(a%j==0)
            {
                cnt--;
            }
        }
        printf("Case %d: %lld\n",i,cnt);
    }

    return 0;
}

 

posted on 2018-04-28 17:17  superhero11  阅读(188)  评论(0编辑  收藏  举报

导航