Description
选择不超过
K
个
Data Constraint
1
≤
Solution
由于
500
以内的质数只有
95
个,加上
1
也只有
对于那些含有两个相同的质因子的数首先可以舍去,剩下的数最多为
306
个。
考虑到
1
~
小于
N−−√
的质数最多也只有
8
个,考虑状压背包,设
一开始先处理不含有大于 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);
}
}