#C231111A. 种树(plant)


#C231111A. 种树(plant)

标签(Label)

  • 数学(因数个数定理)
  • 贪心

网址(Website)

$\qquad$洛谷: 种树

$\qquad$SPOJ:种树 - 题目

$\qquad$题解: 种树 - 题解

题解(Solution)

$\qquad$有一个性质:一个数的因数个数为其质因数分解后每个质数的指数大小+1的乘积。

$\qquad$从这个角度去想就发现会了:每次施肥先把当前的 $w$ 有的质因数 $k$ 扔给当前的 $p_i$ 没有的质因数,这样贡献能直接 $+2$ ,同时让小的数变大总是优于让大的数变的更大的,这个可以用和定差小积大来理解(其实就是一个二次函数的原理)。

$\qquad$然后搞个优先队列(堆)稍稍维护一下就好啦~

$\qquad$时间复杂度:$O(n\sqrt{n}\times logn)$

代码(Code)

#include<bits/stdc++.h>
#include<bitset>
#include<map>
#include<queue>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
#define P pair<int,int>
#define int long long
inline int input(){int x;return cin>>x,x;}
const int mod = 998244353;
const int N = 10123;
bool ST;
priority_queue<P,vector<P>,greater<P>> q; 
bitset<N> vst;
int h[N];
int n,w,ans=1;
int ton[N],use[N];
bool ED;
signed main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n"; 
	string str("plant");
	freopen((str+".in").c_str(),"r",stdin);
	freopen((str+".out").c_str(),"w",stdout);
	cin>>n>>w;For(i,1,n) h[i]=input();
	//w的质因数 
	{
		int x=w,t=sqrt(x);
		for(int j=2;j<=t && x!=1;){
			if(x%j==0) x/=j,vst[j]=true,ton[j]++;
			else j++;
		}if(x!=1) ton[x]++,vst[x]=true;
	}
	
	For(i,1,n){
		map<int,int> mp;
		int x=h[i],t=sqrt(x);
		for(int j=2;j<=t && x!=1;){
			if(x%j==0) x/=j,mp[j]++;
			else j++;
		}if(x!=1) mp[x]++;
		for(int j=vst._Find_first();j<=w;j=vst._Find_next(j)){
			if(!mp.count(j) && ++use[j]<=ton[j]) q.push({0,j});
		}
		for(auto p:mp){
			int x=p.first,k=p.second;
			if(w%x) ans=ans*(k+1)%mod;
			else q.push({k,x});
		}
	}

	while(q.size()){
		int x=q.top().second,k=q.top().first;q.pop();
		if(w!=1 && w%x==0){
			q.push({k+1,x});
			w/=x;
		}else{
			if(k==0) continue;
			ans=ans*(k+1)%mod;
		}
	}
	cout<<ans<<'\n';
	return 0;
}

文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录