LightOJ - 1341 Aladdin and the Flying Carpet (歐拉素數篩+唯一分解定理)

It’s said that Aladdin had to solve seven mysteries before getting the Magical Lamp which summons a powerful Genie. Here we are concerned about the first mystery.
Aladdin was about to enter to a magical cave, led by the evil sorcerer who disguised himself as Aladdin’s uncle, found a strange magical flying carpet at the entrance. There were some strange creatures guarding the entrance of the cave. Aladdin could run, but he knew that there was a high chance of getting caught. So, he decided to use the magical flying carpet. The carpet was rectangular shaped, but not square shaped. Aladdin took the carpet and with the help of it he passed the entrance.
Now you are given the area of the carpet and the length of the minimum possible side of the carpet, your task is to find how many types of carpets are possible. For example, the area of the carpet 12, and the minimum possible side of the carpet is 2, then there can be two types of carpets and their sides are: {2, 6} and {3, 4}.
Input
Input starts with an integer T (≤ 4000), denoting the number of test cases.
Each case starts with a line containing two integers: a b (1 ≤ b ≤ a ≤ 1012) where a denotes the area of the carpet and b denotes the minimum possible side of the carpet.
Output
For each case, print the case number and the number of possible carpets.
Sample Input
2
10 2
12 2
Sample Output
Case 1: 1
Case 2: 2
問題鏈接: http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1341
問題簡述: 輸入兩個整數a,b,求面積爲a並且最短邊大於b且所有邊長均爲整數的矩形有多少個
問題分析: 由題意可得求的是a大於b的因子對數(3,4)與(4,3)算一對。由唯一分解定理可得對於任意正整數一定有a=p1ti×p2t2×…,pi爲a的質因子。則a的因子個數爲k=(t1+1)(t2+1)…(ti+1)
而當b>根號a時矩形個數爲0,直接輸出0。假設小於b的因子個數爲g個,則滿足題意的答案數爲ans=(k-2g)/2個,具體可看代碼及註釋
AC通過的C++語言程序如下:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#include<bitset>
#include<utility>
#include<functional>
#include<iomanip>
#include<sstream>
#define ll long long
#define endl '\n'
#include<ctime>
using namespace std;

const int maxn=1010101;

ll prime[maxn];//素數
ll visit[maxn];
void Prime()//歐拉篩素數
{
    memset(visit,0,sizeof(visit));
    memset(prime,0,sizeof(prime));
    for (int i = 2;i < maxn; i++)
        {
        if (!visit[i])
        {
            prime[++prime[0]] = i;//紀錄素數,prime[0]相當cnt,用來計數
        }
        for (int j = 1; j <=prime[0] && i*prime[j] < maxn; j++)
        {
            visit[i*prime[j]] = 1;
            if (i % prime[j] == 0)
            {
                break;
            }
        }
    }
}

int main()
{
    //ios::sync_with_stdio(false);
    Prime();
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        ll a,b;
        scanf("%lld%lld",&a,&b);
        printf("Case %d: ",i);
        if(b>a/b)//如果b>根號a,直接輸出0
        {
            printf("0\n");
            continue;
        }
        ll ans=1;
        ll tm=0;//質因子的t次數
        ll k=a;
        for(int j=1;j<=prime[0]&&prime[j]*prime[j]<=k;j++)//質因子的平方小於k,並且j小於素數數量
        {
            if(k%prime[j]==0)//如果是質因子
            {
                tm=0;//初始化冪
                while(k%prime[j]==0)//計算出幾次方
                {
                    tm++;
                    k/=prime[j];
                }
                ans*=(tm+1);//因數數量爲質因數次方+1的乘合
            }
        }
        //cout<<ans<<endl;
        if(k>1)//只有剩下一個最大質因數以及1的情況,1則不用乘2
            ans*=2;
        for(int j=1;j<b;j++)//減去小於b的因數
            if(a%j==0) ans-=2;
        ans/=2;//最後除與2即剩一對;(3,4)=(4,3)
        printf("%lld\n",ans);
    }
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章