JZOJ 5464 乘积

Description

选择不超过 K N以内的正整数乘起来,使得乘积不是任何一个质数的平方的倍数,有多少种取法?(每个数只能取一次)

Data Constraint

1 T 5 1 K N 500

Solution

由于 500 以内的质数只有 95 个,加上 1 也只有96个,所以 K 可以先与96取个 min
对于那些含有两个相同的质因子的数首先可以舍去,剩下的数最多为 306 个。
考虑到 1 ~N的每个数最多只有一个大于 N 的质因子,根据 含有的大于 N 的质因子 对数进行分组,显然,同一组内的数最多只能选择一个。

小于 N 的质数最多也只有 8 个,考虑状压背包,设fi,s表示选择了 i 个数,乘积 包含小于N的质因子 的是非状态为 s s为二进制数。

一开始先处理不含有大于 N 的质因子的数的选择方案,然后对于含有大于 N 的质因子的数,由于同一组内的数最多只能选择一个,所以我们一组一组的选数即可。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)

using namespace std;
typedef long long ll;
const ll zd=308,N=256,K=19,M=100,S=8,mo=1e9+7;
int ss[K],pf[K],m2[K],fz[502][zd],g[502],n,m,j,k,i,l,o,t; 
ll f[M][N],c[M][N];
int min(int a,int b)
{return a<b?a:b;}

bool ok(int o)
{
    fo(i,1,S)if(o%pf[i]==0)return false;
    return true;
}

void gx(int y)
{
    fd(i,k,1)
    fo(l,0,N-1)
    if((l&y)==y)f[i][l]=(f[i-1][l^y]+f[i][l])%mo;
}

void change(int o)
{
    fd(i,k,1)
    fo(l,0,N-1)
    fo(j,1,g[o])if((l&fz[o][j])==fz[o][j])f[i][l]=(f[i][l]+f[i-1][l^fz[o][j]])%mo;
} 

int main()
{
    cin>>t;
    ss[1]=2; ss[2]=3; ss[3]=5; ss[4]=7; ss[5]=11; ss[6]=13; ss[7]=17; ss[8]=19; 
    fo(i,1,S)pf[i]=ss[i]*ss[i];
    m2[1]=1; fo(i,2,S+1)m2[i]=m2[i-1]*2;
    fo(tt,1,t){ 
        fo(i,0,M-1)
        fo(l,0,N-1)f[i][l]=0;
        fo(i,1,500)g[i]=0;
        f[0][0]=1;
        cin>>n>>k; k=min(k,M-1); 
        fo(i,1,n)if(ok(i)){
            int p=i,y=0;
            fo(i,1,S)if(p%ss[i]==0)p/=ss[i],y+=m2[i];
            if(p==1)gx(y);else fz[p][++g[p]]=y;
        }
        fo(i,ss[S]+1,n)if(g[i])change(i);
        ll ans=0;
        fo(i,1,k)
        fo(l,0,N-1)ans=(ans+f[i][l])%mo; 
        printf("%lld\n",ans);
    }
 } 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值