bzoj3733 [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-now$的数与当前乘积的乘积大于$n$,就可以直接剪掉了。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 
 6 using namespace std;
 7 
 8 int sum[100010][22],fac[100010],n,k,tot;
 9 
10 il int gi(){
11   RG int x=0,q=1; RG char ch=getchar();
12   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
13   if (ch=='-') q=-1,ch=getchar();
14   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
15   return q*x;
16 }
17 
18 il void factor(RG int n){
19   tot=0;
20   for (RG int i=2;i*i<=n;++i){
21     if (n%i) continue; fac[++tot]=i;
22     if (i*i!=n) fac[++tot]=n/i;
23   }
24   sort(fac+1,fac+tot+1); return;
25 }
26 
27 il int dfs(RG int now,RG int rem,RG int pro){
28   if (!rem) return n==pro;
29   for (RG int i=now;i+rem<=tot+1;++i){
30     if (sum[i][rem]==-1) return 0;
31     if (1LL*pro*sum[i][rem]>n) return 0;
32     if (dfs(i+1,rem-1,pro*fac[i])) return 1;
33   }
34   return 0;
35 }
36 
37 il void work(){
38   n=gi(),k=gi(); if (k==1){ puts("TAK"); return; }
39   if (k==2){ puts(n!=1 ? "TAK" : "NIE"); return; } factor(n),--k;
40   for (RG int i=1;i<=tot;++i){
41     sum[i][0]=1;
42     for (RG int j=1;j<=k;++j){
43       if (sum[i][j-1]==-1 || 1LL*sum[i][j-1]*fac[i+j-1]>n) sum[i][j]=-1;
44       else sum[i][j]=sum[i][j-1]*fac[i+j-1];
45     }
46   }
47   puts(dfs(1,k,1) ? "TAK" : "NIE"); return;
48 }
49 
50 int main(){
51 #ifndef ONLINE_JUDGE
52   freopen("Iloczyn.in","r",stdin);
53   freopen("Iloczyn.out","w",stdout);
54 #endif
55   RG int T=gi();
56   while (T--) work();
57   return 0;
58 }

 

posted @ 2017-10-14 18:24  wfj_2048  阅读(374)  评论(0编辑  收藏  举报