zoukankan      html  css  js  c++  java
  • #2402. 任性(willful)

    题目描述
    俗话说,有钱就是任性。我们的高富帅鱼丸同学打算去看电影。鱼丸到了电影院以后,发现座位的编号正好是 $1$ 到 $200$ 。但是有一些座位号对应的座位坏掉了,没法坐,不妨假设还剩下 $N$ 个能坐的椅子。电影的老板告诉鱼丸,如果你要包下一个集合 $S$ 里的所有椅子,就要付出这些椅子的编号的最小公倍数的钱。鱼丸很任性地同意了。

    来这里玩了很多天以后,鱼丸发现自己正好来了 $2^N-1$ 天,并且由于他非常任性,对于这 $N$ 个椅子的每一种可能的非空子集,他都包下过来看电影。鱼丸大少爷虽然不在乎花了多少钱,但你毕竟是他的助理,于是你想知道鱼丸一共花了多少钱。由于钱的数量实在太大,请对答案 $mod~1e9+7$ 之后输出。

    数据范围
    对于 $100\%$ 的数据,有 $N le 200$

    题解
    考虑到一个数,超过 $13$ 的质因子不超过 $1$ 个

    所以设 $f_{a,b,c,d,e,f}$ 表示 $lcm$ 中 $2$ 的次数 $a$ , $3$ 的次数 $b$ , $5$ 的次数 $c$ , $7$ 的次数 $d$ , $11$ 的次数 $e$ , $13$ 的次数 $f$ 的总和

    然后可以将相同的大质数一起做,具体来说就是多记 $g$ 和 $h$ ,然后 $h$ 表示内部的 $dp$ 值,最后乘上质数即可,然后 $g$ 是在 $f$ 的基础上和 $h$ 一样的转移,最后 $-f-h$ 就是这些数和之前的数的 $lcm$ ,同样最后乘上质数即可,再用 $g$ 和 $h$ 去更新 $f$ 就好了

    细节有点多,考场上心态有点崩(暴力写挂了qwq

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int P=1e9+7,N=205;
    int n,f[8][5][4][3][3][3],g[8][5][4][3][3][3],h[8][5][4][3][3][3],w[8][5][4][3][3][3],p[6]={2,3,5,7,11,13},k[6]={7,4,3,2,2,2},d[6],s,ans;
    struct O{int t[6],x;}a[N];
    bool cmp(O A,O B){return A.x<B.x;}
    void dfs(int x,int y){
        if (x>5){
            (f[max(a[y].t[0],d[0])][max(a[y].t[1],d[1])][max(a[y].t[2],d[2])][max(a[y].t[3],d[3])][max(a[y].t[4],d[4])][max(a[y].t[5],d[5])]+=
            f[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]])%=P;
            (h[max(a[y].t[0],d[0])][max(a[y].t[1],d[1])][max(a[y].t[2],d[2])][max(a[y].t[3],d[3])][max(a[y].t[4],d[4])][max(a[y].t[5],d[5])]+=
            h[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]])%=P;
            return;
        }
        for (int i=k[x];~i;i--) d[x]=i,dfs(x+1,y);
    }
    void geth(int x){
        if (x>5){
            (s+=1ll*h[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]*w[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]%P)%=P;
            return;
        }
        for (int i=k[x];~i;i--) d[x]=i,geth(x+1);
    }
    void getf(int x,int y){
        if (x>5){
            f[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]-=((g[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]+h[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]])%P);
            if (f[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]<0) f[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]+=P;
            (g[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]+=1ll*(f[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]+h[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]])%P*y%P)%=P;
            (s+=1ll*f[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]*w[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]]%P)%=P;
            return;
        }
        for (int i=k[x];~i;i--) d[x]=i,getf(x+1,y);
    }
    void getw(int x){
        if (x>5){
            int &F=w[d[0]][d[1]][d[2]][d[3]][d[4]][d[5]];F=1;
            for (int i=0;i<6;i++)
                for (int j=1;j<=d[i];j++) F=1ll*p[i]*F%P;
            return;
        }
        for (int i=k[x];~i;i--) d[x]=i,getw(x+1);
    }
    int main(){
        scanf("%d",&n);getw(0);
        for (int y,i=1;i<=n;i++){
            scanf("%d",&y);
            for (int j=0;j<6;j++)
                while(y%p[j]==0)
                    a[i].t[j]++,y/=p[j];
            a[i].x=y;
        }
        sort(a+1,a+n+1,cmp);
        for (int i=1;i<=n;i++){
            if (a[i].x==1 || a[i].x!=a[i-1].x)
                memcpy(f,g,sizeof f),memset(h,0,sizeof h);dfs(0,i);
            f[a[i].t[0]][a[i].t[1]][a[i].t[2]][a[i].t[3]][a[i].t[4]][a[i].t[5]]++;
            h[a[i].t[0]][a[i].t[1]][a[i].t[2]][a[i].t[3]][a[i].t[4]][a[i].t[5]]++;
            if (a[i].x==1 || a[i].x!=a[i+1].x){
                s=0;geth(0);(ans+=1ll*s*a[i].x%P)%=P;
                s=0;getf(0,a[i].x);(ans+=1ll*s*a[i].x%P)%=P;
            }
        }
        return printf("%d
    ",ans),0;
    }
  • 相关阅读:
    直面焦虑烦恼 谈谈成长
    Makefile入门1
    递归
    极客时间的专栏
    作者介绍
    1.试除法判定质数 2.分解质因数 质数
    17.没有上司的舞会 树形DP
    17.二分图的最大匹配
    16.染色法判定二分图
    15.Kruskal算法求最小生成树
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11309329.html
Copyright © 2011-2022 走看看