HDU 6125 - Free from square | 2017 Multi-University Training Contest 7

思路来自这里 - -

 

/*
HDU 6125 - Free from square [ 分组,状压,DP ]  |  2017 Multi-University Training Contest 7
题意:
	不超过N的数字中选K个,其乘积不是平方数的倍数
	限制 N,K <= 500
分析:
	小于根号N的质因子至多只有8个,而大于根号N的质因子任意两个乘积大于N
	所以N以内的完全平方数只有两种 
		1. 没有大于根号N的质因子
		2. 有且只有1个大于根号N的质因子
	对于小于根号N的质因子,可以直接按集合状压DP(自身为1组)
	对于大于根号N的质因子,可以将包含该质因子的 非平方数的倍数的数 都归为1组,然后分组DP
	每个数字的状态为其所包含的小于根号N的质因子的集合
	具体DP递推式 为 
		if (a&b == 0) dp[k][a|b] = (dp[k][a|b] + dp[k-1][b]) % MOD;
	其中 a, b为小于8的质因子的集合
*/
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9+7;
const int N = 505;
int p[8] = {2, 3, 5, 7, 11, 13, 17, 19};
int n, t, k;
int dp[N][1<<10];
int st[N], belong[N];
vector<int> v[N];
int solve()
{
    for (int i = 1; i <= n; i++)
    {
        belong[i] = i;
        for (int j = 0; j < 8; j++)
            if (i % p[j] == 0)
            {
                if (i% (p[j]*p[j]) == 0)
                {
                    st[i] = -1; break;
                }
                st[i] |= 1<<j;
                belong[i] /= p[j];
            }
        if (st[i] == -1) continue;
        if (belong[i] == 1) v[i].push_back(i);
        else v[belong[i]].push_back(i);
    }
    dp[0][0] = 1;
    for (int i = 1; i <= n; i++)
    {
        if (st[i] == -1 || v[i].size() == 0) continue;
        for (int l = k; l >= 1; l--)
            for (int j = 0; j < (1<<8); j++)
                for (auto & x : v[i])
                {
                    int p = st[x];
                    if (!(p&j)) dp[l][p|j] = (dp[l][p|j] + dp[l-1][j]) % MOD;
                }
    }
    int ans = 0;
    for (int i = 1; i <= k; i++)
        for (int j = 0; j < (1<<8); j++)
            ans = (ans + dp[i][j]) % MOD;
    return ans;
}
int main()
{
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d", &n, &k);
        memset(dp, 0, sizeof(dp));
        memset(st, 0, sizeof(st));
        for (int i = 1; i <= n; i++) v[i].clear();
        printf("%d\n", solve());
    }
}

  

posted @ 2017-08-16 21:38  nicetomeetu  阅读(133)  评论(0编辑  收藏  举报