您的位置:首页 > 其它

【多校训练】hdu 6125 Free from square 状压dp+分组背包

2017-08-29 19:55 351 查看
Problem Description

There is a set including all positive integers that are not more then n.
HazelFan wants to choose some integers from this set, satisfying: 1. The number of integers chosen is at least 1 and
at most k.
2. The product of integers chosen is 'free from square', which means it is divisible by no square number other than 1. Now please tell him how many ways are there to choose integers, module 10^9+7.

 

Input

The first line contains a positive integer T(1≤T≤5),
denoting the number of test cases.

For each test case:

A single line contains two positive integers n,k(1≤n,k≤500).

 

Output

For each test case:

A single line contains a nonnegative integer, denoting the answer.

 

Sample Input

2
4 2
6 4

 

Sample Output

6
19

题意:

从不大于nn的所有正整数中选出至少11个且至多kk个使得乘积不包含平方因子,对109+710​9​​+7取模。1≤n,k≤5001≤n,k≤500。

思路:

把n个数分成若干组,互斥的放在同一组。

一开始把所有含平方因子的数去除掉,剩下的进行分组。

<sqrt(500)的八个素因子,编成八组,分别为包含2,3,5,7,11,13,17,19素因子的数。 注意包含的数不能重复。
>sqrt(500)的素因子,每一组为包含该素因子的数。
1这个数为一组.

因为其他组可能包含2,3,5,7,11,13,17,19;也就是这八个素因子在其他组也可能出现。

为了判断用状态压缩处理。

dp[k][s]表示选k个,前8个素因子选择状态为s时候的方法数。

dp[k][s] += dp[k-1][s-s1]; (s&s1==s1)


//
//  main.cpp
//  1006
//
//  Created by zc on 2017/8/29.
//  Copyright © 2017年 zc. All rights reserved.
//

#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
const ll MOD=1e9+7;
const int N=505;
bool prime
,v
;
vector<pair<int,int> >r
;
int cnt=0,p
;
ll d
[1<<8];
void init()
{
for(int i=2;i<=N;i++)
{
if(prime[i]==0)
{
for(int j=i;j<=N;j+=i)  prime[j]=1;
p[++cnt]=i;
}
}
memset(v,0,sizeof(v));
for(int i=2;i<=N;i++)
{
if(v[i])    continue;
for(int j=1;j<=8;j++)
{
if(i%(p[j]*p[j])==0)
{
v[i]=1;
break;
}
}
}
for(int i=0;i<=cnt;i++)   r[i].clear();
r[0].push_back(make_pair(1,0));
for(int i=cnt;i>0;i--)
{
for(int j=p[i];j<=N;j+=p[i])
{
if(v[j]) continue;
int s=0;
for(int k=0;k<8;k++)
{
if(j%p[k+1]==0)   s|=(1<<k);
}
r[i].push_back(make_pair(j,s));
v[j]=1;
}
}
}

ll solve(int n,int m)
{
memset(d,0,sizeof(d));
d[0][0]=1;
int ed=1<<8;
for(int i=0;i<=cnt&&p[i]<=n;i++)
for(int j=m;j>0;j--)
for(int k=0;k<r[i].size();k++)
{
if(r[i][k].first>n)   continue;
for(int s=0;s<ed;s++)
{
if((s&r[i][k].second)==r[i][k].second)
{
d[j][s]=(d[j][s]+d[j-1][s-r[i][k].second])%MOD;
}
}
}
ll ans=0;
for(int i=1;i<=m;i++)
for(int j=0;j<ed;j++)
ans=(ans+d[i][j])%MOD;
return ans;
}

int main(int argc, const char * argv[]) {
int T,n,k;
init();
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
printf("%lld\n",solve(n,k));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: