4 2 2 1 4 1 2 5 1 4 4 73 23642 12 20903 29401 2 50 1 1000000000 815180
Case #1: 2 2 Case #2: 4 2 2 Case #3: -1 Case #4: 59200 4 4 5 20 37 [hint] In the second case we have 4 kinds of gunpowder with damage 2, 3, 4, 5. the first bomb is “2”with power of 2 The second bomb is “3” with power of 3 The third bomb is “4” with power of 4 The fouth bomb is “5” with power of 5 The fifth bomb is “2 2” with power of 2 * 2 = 4 So the 4-th bomb with power in the range of 1 to 4 is “2 2”. [/hint]
迷迷糊糊的开始搜索练习,这个是一开始看的题目。
看到的第一个想法,直接暴力搜索,超时!
参考了大神的博客 http://blog.csdn.net/acm_cxlove/article/details/9935667
大致明白了怎么做。。。首先 按题意,解的数的个数在29个之内
计算出每一个长度所对应的解的个数,然后确定题目所求的答案的长度。但枚举最后一层时所花费的时间还是太大。。。继续参考
在再长度n中枚举第n-1的状态,就能计算出每一个n-1所对应的解的个数,从而省去了枚举第n层所花费的时间。。。但还是超时。。。想到剪枝。。不会。。。继续参考
知道当前层所需要乘出的乘积,即可由乘积求出上界和下界,很重要的剪枝!
接下来。。。看代码理解吧
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; typedef long long LL; const LL inf = 1000000000LL; int t; int A,B,L,R,K; int tt,summ,aa[50]; int Pow(int a,int b) { int ans=1; for(int i=1; i<=a; i++) { ans*=b; if(ans>inf||ans<=0) return inf+1; } return ans; } int dfs_len(int c,int a,int b,int l,int r,int k) { if(c==0) return l<=r; if(c==1) { if(l>r) return 0; return max(0,min(b,r)-max(a,l)+1); } int up=min(b,r/Pow(c-1,a)); int down=max(a,l/Pow(c-1,b)); //求第C位数的取值范围 下限为 down*Pow(c-1,b) 上限 up*Pow(c-1,a) int ans=0; for(int i=down; i<=up; i++) { ans+=dfs_len(c-1,i,b,(l+i-1)/i,r/i,k-ans); //求剩余c-1位数的乘积 最小乘积为 l/i 最大乘积为r/i if(ans>k) return ans; } return ans; } int ret; void dfs(int c,int a,int b,int l,int r,int k) { if(c==0) { return ; } if (c == 1) { int num = k + max(l , a) - 1; ret = ret * num; aa[c] = num; return ; } // 上下界 int down = max(a , l / Pow( c - 1 , b)); int up = min (b , r / Pow( c - 1 , a)); for (int i = down ; i <= up ; i ++) { int cnt = dfs_len (c - 1 , i , b , (l + i - 1) / i , r / i , k); if (k > cnt) { k -= cnt; continue; } ret = ret * i; aa[c] = i; dfs (c - 1 , i , b , (l + i - 1) / i , r / i , k); return ; } } int main() { scanf("%d",&t); tt=1; while(t--) { scanf("%d%d%d%d%d",&A,&B,&L,&R,&K); int i; bool flag=false ; printf("Case #%d: ",tt++); for(i=1; i<=30; i++) { int len=dfs_len(i,A,B,L,R,K); if(K>len) { K-=len; continue ; } ret=1; dfs(i,A,B,L,R,K); flag=true ; printf("%d\n",ret); for(int j=i; j>0; j--) if(j==i) printf("%d",aa[j]); else printf(" %d",aa[j]); printf("\n"); break; } if(!flag) printf("-1\n"); /*bool ok = false; printf ("Case #%d: " , tt++); //枚举长度 for (int i = 1 ; i <= 30 ; i ++) { int cnt = dfs_len (i , A , B , L , R , K); if (K > cnt) { K -= cnt; continue; } ret = 1; dfs (i , A , B , L ,R , K); printf ("%d\n" , ret); for (int j = i ; j >= 1 ; j --) { printf ("%d%c" , aa[j] , j == 1 ? '\n' : ' '); } ok = true; break; } if (!ok) puts("-1");*/ } }