Free from square HDU6125

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define mod 1000000007
int T,n,k;
int q[95]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,
233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499};
int a[96][96][256],vis[96][96][256];
int a1[256][9],vis1[256][9];
int subsol(int sg,int k)//可选取范围在小于根号N范围
{
    int res;
    if(k>8)k=8;
    if(k<0)return 0;//不再选
    if(sg==0) return 1;//可选范围为0;那么这一支的贡献返回1,如果把这种选择看成一棵树的话;
    if(vis1[sg][k]) return a1[sg][k];
    int a=0;
    while((1<<a)<=sg)a++;a--;
    res=subsol(sg^(1<<a),k);//不取q[a];
    for(int i=0;i<(1<<a);i++)
    if((sg&i)==i)//i组合状态合法
    {
        int s=q[a];
        for(int j=0;j<a;j++)
        {
            if(i&(1<<j))//j是选好的质数
            {
                s*=q[j];
                if(s>n)break;
            }
        }
        if(s<=n)(res+=subsol(sg^(1<<a)^i,k-1))%=mod;
    }
    vis1[sg][k]=1;
    return a1[sg][k]=res;
}

int sol(int lim,int m,int k,int sg)
{
    int res;
    if(k<0)return 0;//不在取
    if(m<lim) return subsol(sg,k);//大于根号n的质数已经枚举完了
    if(vis[m][k][sg]) return a[m][k][sg];//取第m个且在sg的范围内取K个
    //可以知道这里m都是大于根号n的质数
    res=sol(lim,m-1,k,sg);//不选q[m]的情况
    for(int i=0;i<=255;i++)
    {
        if((sg&i)==i)//如果i在可选区间内,就选
        {
            int s=q[m];//q[m]必选
            for(int j=0;j<=7;j++)//找出选的那些位
            if(i&(1<<j))
            {
               s*=q[j];
               if(s>n)break;//这个数选多了。这个组合不成立
            }
            if(s<=n)//这个组合选取成功,找到了一个数,现在找下一个数
                (res+=sol(lim,m-1,k-1,sg^i))%=mod;//q[m]不能再选了,可选范围也去掉了选过的那些质数
        }
    }
    vis[m][k][sg]=1;//当前值已经找到,省去了重复计算
    return a[m][k][sg]=res;
}

int main()
{
    //freopen("input.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&k);
        memset(vis,0,sizeof vis);
        memset(vis1,0,sizeof vis1);
        if(k>95)k=95;
        double h=sqrt(n)+1e-6;
        int a=0;while(q[a]<=h)a++;
        int b=0;while(q[b]<=n&&b<95)b++;
        int ans=sol(a,b-1,k,(1<<a)-1)+sol(a,b-1,k-1,(1<<a)-1)-1;
        printf("%d\n",ans%mod);//不包含1+包含1-空
    }
    return 0;
}

反向思维,从质因数乘积组成成合法序列入手,可以抽象成一颗乘积的组合树,每一支里面选择的质数互斥;
时间: 2024-08-07 08:39:48

Free from square HDU6125的相关文章

hdu6125 Free from square 分组背包+状态压缩

/** 题目:hdu6125 Free from square 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6125 题意: 从不大于n的所有正整数中选出至少1个且至多k个使得乘积不包含平方因子,对10^9+7取模. 1≤n,k≤500. 思路: 分组背包+状态压缩 把n个数分成若干组,互斥的放在同一组. 一开始把所有含平方因子的数去除掉,剩下的进行分组. <sqrt(500)的八个素因子,编成八组,分别为包含2,3,5,7,11,13,17,19素

[leetcode] 367. Valid Perfect Square

Given a positive integer num, write a function which returns True if num is a perfect square else False. Note: Do not use any built-in library function such as sqrt. Example 1: Input: 16 Returns: True Example 2: Input: 14 Returns: False 使用二分查找寻找input

Project Euler 92:Square digit chains C++

A number chain is created by continuously adding the square of the digits in a number to form a new number until it has been seen before. For example, 44 → 32 → 13 → 10 → 1 → 1 85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89 Therefore any chain that

LeetCode Maximal Square

Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and return its area. For example, given the following matrix: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 Return 4. 思路分析:这题考察DP.缓存中间结果降低反复计算.DP方程为 if(matrix[i][j

Theatre Square 题解代码

Theatre Square CodeForces - 1A 水题水题... 最开始的程序是这个,可是AC不了我也不知道为什么......QAQ... #include <stdio.h>#include<stdlib.h>int main(){    int m,n,a,ans,tmp,k,h,tep,i,j;    scanf("%d %d %d",&m,&n,&a);    if(m%a==0)    {        if(n%a

[LeetCode] Matchsticks to Square 火柴棍组成正方形

Remember the story of Little Match Girl? By now, you know exactly what matchsticks the little match girl has, please find out a way you can make one square by using up all those matchsticks. You should not break any stick, but you can link them up, a

codeforces 710C C. Magic Odd Square(构造)

题目链接: C. Magic Odd Square Find an n × n matrix with different numbers from 1 to n2, so the sum in each row, column and both main diagonals are odd. Input The only line contains odd integer n (1 ≤ n ≤ 49). Output Print n lines with n integers. All the

hdu1518(Square)深搜+剪枝

点击打开杭电1518 Problem Description Given a set of sticks of various lengths, is it possible to join them end-to-end to form a square? Input The first line of input contains N, the number of test cases. Each test case begins with an integer 4 <= M <= 20,

poj 1084 Square Destroyer dlx解重复覆盖

分析: 将问题转化为重复覆盖问题,DancingLink解决. 代码: //poj 1084 //sep9 #include <iostream> using namespace std; const int maxN=10024; const int maxL=128; int L[maxN],R[maxN],U[maxN],D[maxN]; int C[maxN],H[maxN]; int S[maxN],A[maxN],X[maxN]; bool makeup[maxL][maxL];