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) .
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.
A single line contains a nonnegative integer, denoting the answer.
Sample Input
2 4 2 6 4
Sample Output
6 19
题意:
从不大于n的所有正整数中选出至少1个且至多k个使得乘积不包含平方因子,对109+7取模。1≤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[N],v[N];
vector<pair<int,int> >r[N];
int cnt=0,p[N];
ll d[N][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));
}
}