Lyft Level 5 Challenge 2018 - Elimination Round D. Divisors (数论,二分)
-
题意:给你\(n\)个数,每个数都有\(3\)~\(5\)个因数,问你将这\(n\)个数累乘后的因子数.
-
题解:对于求约数个数,很容易想到唯一分解定理:\(x=p_1^{a_1}*p_2^{a_2}*...p_k^{a_k}\),然后就能计算出因子数:\((a_1+1)*(a_2+1)*...(a_k+1)\).但是这题的数据给的太大,不能直接计算,但是却给了限制条件:每个数有\(3\)~\(5\)个因子.那么我们根据质因数分解,不难发现一个数只有一下4中合法情况.
1.\(p_1*p_2\) 2.\(p_1^{2}\) 3.\(p_1^{3}\) 4.\(p_1^{4}\)
想一想,我们最后要得到答案,那么一定是根据累乘得到的数做质因数分解后根据质因子的指数算出来的.所以我们现在需要做的,就是算出每个质因数的指数,2,3,4这三种情况我们可以直接得到,用map来维护质数的个数,之后就只剩下第一种情况没有找,我们可以去遍历这些剩下的数.
假如这些剩下的数中,某一个数的\(p_1\)和\(p_2\)都没有在除了自己这个数之外的任何一个数中出现,那么我们就找不到这个数具体的\(p_1\)和\(p_2\),但是却可以统计这个数的次数\(num\)后,直接将其贡献\((num+1)^2\)给答案(因为\(p_1\),\(p_2\)只在这个数出现,最后\(p_1\)和\(p_2\)的次数就是这个数出现的次数).
那么最后就是剩下的数中,某些数\(a_i\)的\(p_1\)和\(p_2\)在其他的数中出现了,那么我们就可以用\(gcd\)来求出\(p_1\)或者\(p_2\),然后\(a[i]/(p_1\ or\ p_2)\)来得到另一个质数,map更新这两个质数的次数即可.
得到所有质数的指数之后(不包括找不到的),就是用唯一分解定理算答案.
这道题用二分来判断根操作可以当作板子来记一下
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 998244353; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n; ll a[N]; bool st[N]; ll check(int k,ll l,ll r,ll x){ if(l==r) return l; ll mid=(l+r)>>1; ll tmp=1; rep(i,1,k) tmp*=mid; if(tmp<x) return check(k,mid+1,r,x); else return check(k,l,mid,x); } int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n; map<ll,ll> mp; map<ll,ll> indv; rep(i,1,n){ cin>>a[i]; ll r_4=check(4,1,40000,a[i]); ll r_3=check(3,1,1300000,a[i]); ll r_2=check(2,1,1500000000,a[i]); if(r_4*r_4*r_4*r_4==a[i]) mp[r_4]+=4; else if(r_3*r_3*r_3==a[i]) mp[r_3]+=3; else if(r_2*r_2==a[i]) mp[r_2]+=2; else st[i]=true; } rep(i,1,n){ if(st[i]){ bool flag=false; rep(j,1,n){ ll d=gcd(a[i],a[j]); if(d==1 || a[i]==a[j]) continue; mp[d]++; mp[a[i]/d]++; flag=true; break; } if(!flag) indv[a[i]]++; } } ll ans=1; for(auto w:indv){ //找不到的p1和p2的数的贡献 ans=(ans*(w.se+1)*(w.se+1))%mod; } for(auto w:mp){ ans=(ans*(w.se+1))%mod; } cout<<ans<<'\n'; return 0; }