dtoj2402. 任性(willful)

 

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

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


Sol.

本题 $ N leq 200 $。

lcm中指数大于1的只能是2,3,5,7,11,13.

令f[i][a][b][c][d][e][f]表示前i个数,他们的指数是a,b,c,d,e,f的答案;

转移时只要看这个数加不加入就行。

那我们还得加上那些其他的质数。

我们考虑把那个大质数拉出来排序。

每次处理含有相同大质数的数。

那么在f后面多一维[0/1]表示当前处理的大指数是否出现过即可。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define For for(int a=0;a<8;a++)for(int b=0;b<5;b++)for(int c=0;c<4;c++)for(int d=0;d<3;d++)for(int e=0;e<3;e++)for(int f=0;f<3;f++)
#define S [a][b][c][d][e][f]
#define ns [max(a,s[i].t[0])][max(b,s[i].t[1])][max(c,s[i].t[2])][max(d,s[i].t[3])][max(e,s[i].t[4])][max(f,s[i].t[5])]
#define mod 1000000007
#define ll long long
using namespace std;
int n,p[6]={2,3,5,7,11,13},ans;
ll g[202][8][5][4][3][3][3][2],dp[8][5][4][3][3][3];
struct node{
    int M,t[6];
}s[202];
bool cmp(node A,node B){return A.M<B.M;}
int w(int a,int num){
    if(num<=0)return 1;
    int A=1;for(;num;num>>=1,a=a*a%mod)if(num&1)A=A*a;return A;
}
int calc(int i,int a,int b,int c,int d,int e,int f){
    return w(p[0],s[i].t[0]-a)*w(p[1],s[i].t[1]-b)*w(p[2],s[i].t[2]-c)*w(p[3],s[i].t[3]-d)*w(p[4],s[i].t[4]-e)*w(p[5],s[i].t[5]-f);
}
int main(){
    cin>>n;
    for(int i=1,v;i<=n;i++){
        scanf("%d",&v);
        for(int j=0;j<6;j++)while(v%p[j]==0)v/=p[j],s[i].t[j]++;
        s[i].M=v;
    }
    sort(s+1,s+n+1,cmp);
    dp[0][0][0][0][0][0]=1;
    for(int i=1;i<=n;i++){
        if(s[i].M!=s[i-1].M)For g[i-1]S[0]=dp S,g[i-1]S[1]=0; 
        
        For g[i]S[0]=g[i-1]S[0],g[i]S[1]=g[i-1]S[1];
        For{
            (g[i]ns[1]+=g[i-1]S[0]*s[i].M%mod*calc(i,a,b,c,d,e,f)%mod)%=mod;
            if(s[i].M==s[i-1].M)(g[i]ns[1]+=g[i-1]S[1]*calc(i,a,b,c,d,e,f))%=mod;
        }
        if(s[i].M!=s[i+1].M)For dp S= (g[i]S[0]+g[i]S[1])%mod;
    }
    For (ans+=dp S)%=mod;
    cout<<ans-1<<endl;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liankewei/p/12301750.html