1. 程式人生 > >【Atcoder - AGC003D】Anticube

【Atcoder - AGC003D】Anticube

@[email protected]


@Problem [email protected]

Snuke got positive integers s1,…,sN from his mother, as a birthday present. There may be duplicate elements.

He will circle some of these N integers. Since he dislikes cubic numbers, he wants to ensure that if both si and sj(i≠j) are circled, the product si*sj is not cubic. For example, when s1=1,s2=1,s3=2,s4=4, it is not possible to circle both s1 and s2 at the same time. It is not possible to circle both s3 and s4 at the same time, either.

Find the maximum number of integers that Snuke can circle.

Constraints
1≦N≦10^5
1≦si≦10^10
All input values are integers.

Input
The input is given from Standard Input in the following format:
N
s1
:
sN
Output
Print the maximum number of integers that Snuke can circle.

Sample Input 1
8
1
2
3
4
5
6
7
8
Sample Output 1


6
Snuke can circle 1,2,3,5,6,7.

Sample Input 2
6
2
4
8
16
32
64
Sample Output 2
3

Sample Input 3
10
1
10
100
1000000007
10000000000
1000000009
999999999
999
999
999
Sample Output 3
9

@[email protected]

Snuke 收到了一份特殊的生日禮物:N 個正整數!
Snuke 認為兩個數是“不相配”的,當且僅當這兩個數的乘積為立方數。
現在 Snuke 想要從 N 個數中選出儘量多的數,使得這些數兩兩“相配”。

@[email protected]

首先,可以想到的第一個操作肯定是把每一個數的立方因子去掉。

然後從唯一分解式考慮:令 x = p 1 a 1 p 2 a 2 . . . p k a k x = p_1^{a_1}*p_2^{a_2}*...*p_k^{a_k}
去掉立方因子得到: x = p 1 a 1 m o d    3 p 2 a 2 m o d    3 . . . p k a k m o d    3 x' = p_1^{a_1\mod3}*p_2^{a_2\mod3}*...*p_k^{a_k\mod3}
則如果 y y 使得 y = p 1 ( 3 a 1 ) m o d    3 p 2 ( 3 a 2 ) m o d    3 . . . p k ( 3 a k ) m o d    3 y' = p_1^{(3-a_1)\mod3}*p_2^{(3-a_2)\mod3}*...*p_k^{(3-a_k)\mod3} ,x 和 y 的乘積為立方數。

可以發現一個 x’ 對應著唯一的 y’。
假如有 p 個數去掉立方因子後得到 x’, q 個數去掉立方因子後得到 y’。
則我們要麼選這 p 個數,要麼選這 q 個數。因此對答案的貢獻 max(p, q)。

我們對於每一個數 x 求出它對應的 x’ 與 y’,然後統計相應的個數,最後再取max。

但是還有特殊情況:如果 x’ = y’。即:如果這個數本身就是一個完全平方數。
我們不能選兩個以上的完全平方數,但一定可以選一個完全平方數。
因此標記一下是否有完全平方數即可。

講講實現上的一些問題:
可以發現最多有兩個質因子 > x 的立方根。
我們先篩出 ≤ x 的立方根的質數,然後用這些質數對 x 進行處理。
假如從 x 中除去這些因數後:
1)變為了 1,則 x 沒有任何 > x 的立方根的質因子。
2)變為了一個完全平方數,則 x 有兩個相同的 > x 的立方根的質因子。
3)變為了一個非完全平方數,則 x 要麼有一個 > x 的立方根的質因子,要麼有兩個不相同的 > x 的立方根的質因子。
三種情況皆不影響 x’,但會影響 y’。根據唯一分解式推導一下就可以了。

@[email protected]

理論上來說……這道題應該會爆long long才對。
但是好像是因為我用的map,所以變成了負數也影響不大……
如果對於我的題解或者我的程式碼有任何的疑問,可以留言在下面,我會盡力解疑的qwq。

#include<map>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAX = 2160;
const int MAXN = 100000;
int prm[MAX + 5], pcnt = 0;
bool is_prm[MAX + 5];
void init() {
	for(int i=2;i<=MAX;i++) {
		if( !is_prm[i] )
			prm[++pcnt] = i;
		for(int j=1;i*prm[j]<=MAX;j++) {
			is_prm[i*prm[j]] = true;
			if( i % prm[j] == 0 ) break;
		}
	}
}
ll s[MAXN + 5], a[MAXN + 5], b[MAXN + 5];
ll IsSqr(ll x) {
	ll le = 1, ri = 100000;
	while( le < ri ) {
		ll mid = (le + ri) >> 1;
		if( mid * mid >= x ) ri = mid;
		else le = mid + 1;
	}
	return (ri * ri == x) ? ri : 0;
}
map<ll, int>mp;
int siz[2*MAXN + 5];
int main() {
	init(); int N;
	scanf("%d", &N);
	int ans = 0, flag = false;
	for(int i=1;i<=N;i++) {
		a[i] = b[i] = 1;
		scanf("%lld", &s[i]);
		for(int j=1;j<=pcnt;j++) {
			int cnt = 0;
			while( s[i] % prm[j] == 0 ) {
				cnt++;
				s[i] /= prm[j];
			}
			cnt %= 3;
			if( cnt == 1 ) {
				a[i] *= prm[j];
				b[i] *= prm[j] * prm[j];
			}
			else if( cnt == 2 ) {
				a[i] *= prm[j] * prm[j];
				b[i] *= prm[j];
			}
		}
		if( IsSqr(s[i]) ) {
			a[i] *= s[i];
			b[i] *= IsSqr(s[i]);
		}
		else {
			a[i] *= s[i];
			b[i] *= s[i] * s[i];
		}
		if( !flag && a[i] == 1 && b[i] == 1 )
			flag = true;
	}
	for(int i=1;i<=N;i++) {
		if( a[i] == 1 && b[i] == 1 ) continue;
		if( mp.count(a[i]) )
			siz[mp[a[i]]]++;
		else {
			mp[a[i]] = i;
			mp[b[i]] = i+N;
			siz[i]++;
		}
	}
	for(int i=1;i<=N;i++) {
		if( mp[a[i]] == i )
			ans += max(siz[i], siz[i+N]);
	}
	if( flag ) ans++;
	printf("%d\n", ans);
}

@[email protected]

就是這樣,新的一天裡,也請多多關照哦(ノω<。)ノ))☆.。