1. 程式人生 > >bzoj3733 [Pa2013]Iloczyn

bzoj3733 [Pa2013]Iloczyn

name cto urn bits names color clu getc output

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 }

bzoj3733 [Pa2013]Iloczyn