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 }