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;
    }
    数列
  • 相关阅读:
    Find the Smallest K Elements in an Array
    Count of Smaller Number
    Number of Inversion Couple
    Delete False Elements
    Sort Array
    Tree Diameter
    Segment Tree Implementation
    Java Programming Mock Tests
    zz Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
    Algorithm about SubArrays & SubStrings
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13939745.html
Copyright © 2011-2022 走看看