• [BZOJ3733]Iloczyn


    Description

    给定正整数n和k,问能否将n分解为k个不同正整数的乘积

    Input

    第一行一个数T(T<=4000)表示测试组数
    接下来T行每行两个数n(n<=10^9),k(k<=20)

    Output

    输出T行,若可以被分解,输出"TAK"否则输出"NIE"

    Sample Input

    3
    15 2
    24 4
    24 5

    Sample Output

    TAK
    TAK
    NIE
     
    好久不写搜索果然没什么剪枝的思路,其实这道题的剪枝也很好想
    关键是效果非常显著
    我们设$DFS(x,y,z)$表示到选到第$x$个因数还有$y$个没选乘积为$z$是否合法
    然后我们预处理出来$f[i][j]$表示从$i$开始再选最小的$j$个的最小乘积
    如果当前$z*f[x][y]>n$就一定没有合法方案了,加上这个剪枝后跑的飞快
    代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define M 2010
     5 using namespace std;
     6 int T,n,k,tot;
     7 int q[M],f[M][22];
     8 bool dfs(int x,int y,int z) 
     9 {
    10     if(!y) return n==z;--y;
    11     while(x+y<=tot) 
    12     {
    13         if(f[x][y]<0) return false;
    14         if(1ll*f[x][y]*z>n) return false;
    15         if(dfs(x+1,y,z*q[x])) return true;
    16         x++;
    17     }
    18     return false;
    19 }
    20 int main()
    21 {
    22     scanf("%d",&T);
    23     while(T--) 
    24     {
    25         scanf("%d%d",&n,&k);tot=0;
    26         for(int i=1; i*i<=n; i++)
    27             if(n%i==0) 
    28             {
    29                 q[++tot]=i;
    30                 if(n/i!=i) q[++tot]=n/i;
    31             }
    32         sort(q+1,q+1+tot);
    33         for(int i=1; i<=tot; i++) 
    34         {
    35             long long t=1;
    36             for(int j=0; j<k&&(i+j)<=tot; f[i][j++]=t)
    37                 if(t>0) {t*=q[i+j];if(t>n) t=-1;}
    38         }
    39         if(dfs(1,k,1)) puts("TAK");
    40         else puts("NIE");
    41     }
    42     return 0;
    43 }
  • 相关阅读:
    Python生成器
    Python迭代器
    模块
    列表推倒式
    内置函数 lambda表达式
    函数
    global、nonlocal、迭代器
    练习
    编码数组字典
    字典
  • 原文地址:https://www.cnblogs.com/Slrslr/p/10014986.html
Copyright © 2020-2023  润新知