2010-1134
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
'''题意'''
我们称一个数为square-free number当且仅当这个数是一个整数并且它不被除了1以外的其它正整数的平方整除。如果一个集合只包含square-free number,那么我们称这个集合为square-free set。定义一个集合的乘积表示该集合所包含元素的乘积。对于一个集合A,若A不仅是square-free set,并且A的乘积也是square-free number,那么我们称A是一个perfect set。
给你两个数n和k,请你求出包含不多于k个元素,且每个元素均属于[1, n]的非空perfect set的数目。(n, k <= 500)
'''题解'''
搜索+记忆化。[[BR]]
因为所以元素不超过500,而又必须是square-free number,所以对于一个元素的质因数分解没有重复的因子出现,并且不会超过4个,因为2*3*5*7=210,同时因子的只能是1到500间的质数,所以范围很小,可以直接搜。
'''代码'''
{{{
#include<vector>
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
#define sqr(x) ((x)*(x))
using namespace std;
const int rest = 1000000007;
map<pair<int, pair<int, vector<int> > >, int> d;
vector<int> prim;
int n, k;
int dfs(int cur, int num, vector<int> a)
{
if (cur == prim.size()) return (num > 0);
while (a.size() > 0 && a[a.size() - 1] * prim[cur] > n) a.pop_back();
pair<int, pair<int, vector<int> > > tp = make_pair(cur, make_pair(num, a));
if (d.find(tp) != d.end()) return d[tp];
int val;
val = dfs(cur + 1, num, a);
vector<int> b;
if (num < k)
{
b = a; b.push_back(prim[cur]);
sort(b.begin(), b.end());
val = (val + dfs(cur + 1, num + 1, b)) % rest;
}
for (int i = 0; i < a.size(); i++)
{
b = a; b[i] = b[i] * prim[cur];
sort(b.begin(), b.end());
val = (val + dfs(cur + 1, num, b)) % rest;
}
d[tp] = val; return val;
}
class SquareFreeSets
{
public:
int countPerfect(int N, int K)
{
n = N; k = K;
for (int i = 2; i <= N; i++)
{
bool flag = true;
for (int j = 2; j * j <= i; j++)
if (i % j == 0)
{
flag = false; break;
}
if (flag) prim.push_back(i);
}
vector<int> st;
return dfs(0, 0, st);
}
};
int main()
{
// freopen("square.in", "r", stdin);
// freopen("square.out", "w", stdout);
int N, K;
while (cin >> N >> K) {
prim.clear();
vector<int>().swap(prim);
d.clear();
cout << SquareFreeSets().countPerfect(N, K) << endl;
}
return 0;
}
}}}
题意
我们称一个数为square-free number当且仅当这个数是一个整数并且它不被除了1以外的其它正整数的平方整除。如果一个集合只包含square-free number,那么我们称这个集合为square-free set。定义一个集合的乘积表示该集合所包含元素的乘积。对于一个集合A,若A不仅是square-free set,并且A的乘积也是square-free number,那么我们称A是一个perfect set。
给你两个数n和k,请你求出包含不多于k个元素,且每个元素均属于[1, n]的非空perfect set的数目。(n, k <= 500)
题解
搜索+记忆化。
因为所以元素不超过500,而又必须是square-free number,所以对于一个元素的质因数分解没有重复的因子出现,并且不会超过4个,因为2*3*5*7=210,同时因子的只能是1到500间的质数,所以范围很小,可以直接搜。
代码
#include<vector>
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
#define sqr(x) ((x)*(x))
using namespace std;
const int rest = 1000000007;
map<pair<int, pair<int, vector<int> > >, int> d;
vector<int> prim;
int n, k;
int dfs(int cur, int num, vector<int> a)
{
if (cur == prim.size()) return (num > 0);
while (a.size() > 0 && a[a.size() - 1] * prim[cur] > n) a.pop_back();
pair<int, pair<int, vector<int> > > tp = make_pair(cur, make_pair(num, a));
if (d.find(tp) != d.end()) return d[tp];
int val;
val = dfs(cur + 1, num, a);
vector<int> b;
if (num < k)
{
b = a; b.push_back(prim[cur]);
sort(b.begin(), b.end());
val = (val + dfs(cur + 1, num + 1, b)) % rest;
}
for (int i = 0; i < a.size(); i++)
{
b = a; b[i] = b[i] * prim[cur];
sort(b.begin(), b.end());
val = (val + dfs(cur + 1, num, b)) % rest;
}
d[tp] = val; return val;
}
class SquareFreeSets
{
public:
int countPerfect(int N, int K)
{
n = N; k = K;
for (int i = 2; i <= N; i++)
{
bool flag = true;
for (int j = 2; j * j <= i; j++)
if (i % j == 0)
{
flag = false; break;
}
if (flag) prim.push_back(i);
}
vector<int> st;
return dfs(0, 0, st);
}
};
int main()
{
// freopen("square.in", "r", stdin);
// freopen("square.out", "w", stdout);
int N, K;
while (cin >> N >> K) {
prim.clear();
vector<int>().swap(prim);
d.clear();
cout << SquareFreeSets().countPerfect(N, K) << endl;
}
return 0;
}