2020/10/27 模拟赛 数列

Description

小 s 的毒瘤数学老师布置了一个毒瘤问题,于是他去询问小 r。 小 s 给了小 r 一个正整数 $N$,并且保证$N$ 的不同质因子个数不超过 $6$。 现在从一个空数列开始,把$N$ 的因数一个一个加到数列中,每次加入的数可能重复,但必须都大 于$1$ 。 每次添加新的数字的时候,需要保证这个数 $x$与数列中已有的数至多一个有大于$1$ 的公因数。 例如,当$N$等于 12156144 的时候, (42),(66,7,7,23,299,66),(42,12156144) 是合法的, 而数列 (5,11) 是不合法的,因为 5 不是 12156144 的因数,数列 (66,13,143) 也是不合法的,因为 143 与其他两个数有大于 1 的公因数。 小 s 想要知道,共有多少个不同的数列满足以上条件。 特别地,两个数列不同,当且仅当他们的长度不同或某一处的数不同。

Solution

考虑逐位确定数列,因为在数列中每个质因数最多出现2次,发现答案只与当前选择到第几位和之前出现次数为1的因数的划分方式有关

记忆化搜索,总状态数为$\sum_{i=0}^6 Bell_i\binom{6}{i}2^{6-i} $

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
long long n,temp,cnt=-1,prime[10],pc[10],num[70],col[10];
const long long mod=1e9+7;
map<long long,long long>mp[15];
inline long long read()
{
    long long f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return f*w;
}
bool check(long long s,long long t)
{
    long long tot=0;
    memset(col,0,sizeof(col));
    for(long long i=0;i<=cnt;i++)
    {
        if(t>>i&1)
        {
            long long v=s>>3*i&7;
            if(v==7)
            {
                return false;
            }
            if(v&&!col[v])
            {
                col[v]=++tot;
            }
            if(tot>1)
            {
                return false;
            }
        }
    }
    return true;
}
long long trans(long long s,long long t)
{
    long long r=0,tot=0;
    for(long long i=0;i<=cnt;i++)
    {
        long long v=s>>3*i&7;
        if(v<7)
        {
            tot=max(tot,v);
        }
    }
    for(long long i=0;i<=cnt;i++)
    {
        long long v=s>>3*i&7;
        if(v==7)
        {
            r|=7<<3*i;
        }
        else
        {
            if(v)
            {
                if(t>>i&1)
                {
                    r|=7<<3*i;
                }
                else
                {
                    r|=v<<3*i;
                }
            }
            else
            {
                if(t>>i&1)
                {
                    r|=tot+1<<3*i;
                }
            }
        }
    }
    s=r;
    tot=0;
    r=0;
    memset(col,0,sizeof(col));
    for(long long i=0;i<=cnt;i++)
    {
        long long v=s>>3*i&7;
        if(v==7)
        {
            r|=7<<3*i;
        }
        else if(v)
        {
            if(!col[v])
            {
                col[v]=++tot;
            }
            r|=col[v]<<3*i;
        }
    }
    return r;
}
long long dfs(long long k,long long s)
{//cout<<k<<" "<<s<<endl;
    if(mp[k][s])
    {
        return mp[k][s];
    }
    long long ret=!!k;
    for(long long i=1;i<1<<(cnt+1);i++)
    {
        if(check(s,i))
        {
            (ret+=1ll*dfs(k+1,trans(s,i))*num[i]%mod)%=mod;
        }
    }
    return mp[k][s]=ret;
}
int main()
{
    n=read();
    temp=n;
    for(long long i=2;i*i<=temp;i++)
    {
        if(!(temp%i))
        {
            prime[++cnt]=i;
            while(!(temp%i))
            {
                temp/=i;
                ++pc[cnt];
            }
        }
    }
    if(temp>1)
    {
        prime[++cnt]=temp;
        pc[cnt]=1;
    }
    for(long long i=1;i<1<<(cnt+1);i++)
    {
        num[i]=1;
        for(long long j=0;j<=cnt;j++)
        {
            if(i>>j&1)
            {
                num[i]*=pc[j];
            }
        }
    }
    printf("%d\n",dfs(0,0));
    return 0;
}
数列

 

posted @ 2020-11-07 07:40  QDK_Storm  阅读(142)  评论(0编辑  收藏  举报