1. 程式人生 > >BZOJ 3733 [Pa2013]Iloczyn 模擬爆搜

BZOJ 3733 [Pa2013]Iloczyn 模擬爆搜

name names std else != define algo getchar class

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 }

BZOJ 3733 [Pa2013]Iloczyn 模擬爆搜