当前位置: 代码迷 >> 综合 >> H - A Partial Order Relation UVALive - 8270
  详细解决方案

H - A Partial Order Relation UVALive - 8270

热度:97   发布时间:2023-11-29 20:38:19.0

题目链接

题意:这个题类似于求离散数学中的求哈斯图,就是从最高点开始,一层一层的找因子,但同层之间不可以出现能够互相整除的数。

题解:因为是求因子数,我们可以想到将他们拆分,拆分到不能再拆分的几个数相乘,所以我们可以想到拆分成质因子。例如:120=2 * 2 * 2 *3 * 5;
我们最初思考的时候应该是从120这个最大值思考,但是分成最小值后我们要从这个最底层思考,本来想的是从最大值开始,每次选的时候少选一个看有几种选法,但是因为上层结果重复的要记录但是下层要去重,这样计算起来很麻烦,也找不到任何规律,所以正难则反,3我们可以从底层开始,从1开始,1 -> 2 ->4->8(最多可以选择3个2),3->6->12->24,5->10->15->30
15->30->60->120共有3 * 2 * 2个,底层选完了2 可以选择3,因为3只可以选择1个,1->3,2->6,4->12,8->16,5->15,10->30,20->40,40->80,共1 * 4 * 2个,选5的时候相同,这里不再列举,我们可以发现,每一种选择都对应着一根线,所以共有num[i] * (num[j]+1)…,其中num就是相同数的个数
下面是AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
const int N=1e6+10;
ll fa[N];
ll prime[N],cnt;
ll nn,fcnt;
bool st[N];
void getprime()
{
    int i,j;for(i=2;i<=N;i++)//预处理的将最大值设为1e6左右即可,因为2 ^ 40 大概在1e12左右所以求出1e6左右的数即可,{
    if(!st[i]) prime[cnt++]=i;for(j=0;j<cnt&&prime[j]<=N/i;j++){
    st[i*prime[j]]=true;if(i%prime[j]==0) break;}}
}
void f()
{
    fcnt=0;ll temp=nn;for(ll i=0;prime[i]*prime[i]<=temp;i++){
    if(temp%prime[i]==0){
    while(temp%prime[i]==0){
    fa[fcnt]++;temp/=prime[i];}fcnt++;}}if(temp>1) fa[fcnt++]=1;
}
int main()
{
    getprime(); //这里需要对素数预处理出来否则在循环里面找会超时。int t;cin>>t;while(t--){
    memset(fa,0,sizeof(fa));cin>>nn;f();ll sum=0;for(ll i=0;i<fcnt;i++){
    ll res=fa[i];for(ll j=0;j<fcnt;j++){
    if(j!=i)res*=(fa[j]+1);}sum+=res;}printf("%lld\n",sum);}return 0;
}
  相关解决方案