1. 程式人生 > >數論題集1-7 (唯一分解定理+約數個數求和+素篩)Aladdin and the Flying Carpet

數論題集1-7 (唯一分解定理+約數個數求和+素篩)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.

題意:

給你一個長方形面積和一個最小可能的邊長,統計有多少種滿足面積相等且邊長大於等於最小邊長的長方形。

思路:

唯一分解定理:任何一個大於1的自然數 N,如果N不為質數,那麼N可以唯一分解成有限個質數的乘積N=P1^a1 * P2^a2 * P3^a3 ...... Pn^an;

約數個數求和:(a1+1)(a2+1)(a3+1)…(ak+1)    其中a1、a2、a3…ak是p1、p2、p3,…pk的指數。

比如   12 有   [3 , 4]  [2 , 6]  倆對 , [3 , 4]與[4 , 3]算一對 。 資料範圍是1e12 , 所以我們可以打表1e6內的素數,然後求出n以內的因子個數,再減去1 ~ a之間可以整除 n 的個數 ,就是答案。

因為我們打表的素數範圍是1e6 , 所以如果一個數是超過1e6的素數  或者比如1e12 , 那麼1e2我們就可以找到但是1e10超過了範圍找不到 , 所以這裡有個判斷:

	if(n > 1)
	sum *= 2;
	return sum;

大概也就沒什麼坑點了

貼程式碼:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1008000;
int prime[maxn] , k , vis[maxn];
void Prime()
{
	 k = 0;
	memset(vis , 0 , sizeof(vis));
	for(int i = 2 ; i < maxn ; i++)
	{
		if(!vis[i])
		{
			prime[k++] = i;
			for(int j = 2 ; i * j < maxn ; j++)
			{
				vis[i*j] = 1;
			} 
		}
	}
}
ll solve(ll n)//K素數個數 
{
	ll sum = 1;
	for(int i = 0 ; i < k && prime[i] * prime[i] <= n ; i++)
	{
		if(n % prime[i] == 0)
		{
			int ans = 0;
			while(n % prime[i] == 0)
			{
				ans++;
				n /= prime[i];
			}
			sum *= (1+ans);
		}
		
	}
	if(n > 1)
	sum *= 2;
	return sum;
}
int main()
{
	int T  , t =  1;
	
	cin >> T;
	Prime();
	while(T--)
	{
		ll a , b;
		cin >> a >> b;
		if(a <= b* b)
		{
			printf("Case %d: 0\n" , t++);
			continue;
		}
		ll num = solve(a);
		num /= 2;
		for(int i = 1 ; i < b ; i++)
		{
			if(a % i == 0)
			{
				num--;
			}
		}
		printf("Case %d: %lld\n" , t++ , num);
	}
	return 0;
 }