BZOJ 3733 [Pa2013]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

题解 
搜索+剪枝,先求出所有因数,然后暴力搜索,剪枝就是如果后面最小的k个数当前数相乘大于n就退出。

 

orz wsj大佬

 1 #include<cstring>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdio>
 6 
 7 #define N 10007
 8 #define ll long long
 9 using namespace std;
10 inline int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
14     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 
18 int n,k,tot,p[N];
19 ll f[N][30];
20 
21 bool dfs(int now,int k,int tmp)
22 {
23     if (!k) return tmp==n;
24     k--;
25     for (;now+k<=tot;now++)
26     {
27         if (f[now][k]<0) return 0;
28         if (f[now][k]*tmp>n) return 0;
29         if (dfs(now+1,k,tmp*p[now])) return 1;
30     }
31     return 0;
32 }
33 inline void solve()
34 {
35     n=read();k=read();tot=0;
36     for (int i=1;i*i<=n;i++)
37         if (n%i==0)
38         {
39             p[++tot]=i;
40             if (i*i!=n) p[++tot]=n/i;
41         }
42     sort(p+1,p+tot+1);
43     for (int i=1;i<=tot;i++)
44     {
45         ll tmp=1;
46         for (int j=0;j<k&&i+j<=tot;f[i][j++]=tmp)
47             if (tmp>0)
48             {
49                 tmp*=p[i+j];
50                 if (tmp>n) tmp=-1;
51             }
52     }
53     if (dfs(1,k,1)) puts("TAK");
54     else puts("NIE");
55 }
56 int main()
57 {
58     int Case=read();
59     while (Case--)
60         solve();
61 }

 

posted @ 2017-12-29 10:07  Kaiser-  阅读(281)  评论(0编辑  收藏  举报