zoukankan      html  css  js  c++  java
  • 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_iinom{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
    ",dfs(0,0));
        return 0;
    }
    数列
  • 相关阅读:
    函数与递归、第五章习题
    第四章习题continue、break
    程序异常处理
    第一章习题
    第三章习题.split('')
    文本进度条
    字符串处理函数、Unicode
    字符串处理.<方法>()
    springbatch
    卸载gitlab
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13939745.html
Copyright © 2011-2022 走看看