1. 程式人生 > >HDU 5936 Difference(折半搜索(中途相遇法))

HDU 5936 Difference(折半搜索(中途相遇法))

mes diff while pri ges void spa pre pro

http://acm.hdu.edu.cn/showproblem.php?pid=5936

題意:
技術分享

定義了這樣一種算法,現在給出x和k的值,問有多少個y是符合條件的。

思路:

y最多只有10位,再多x就是負的了。

這樣的話可以將y分為前後兩部分,我們先枚舉後5位的情況,然後再枚舉前5位的情況,通過二分查找找到匹配的項,這樣就大大的降低了時間復雜度。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5
#include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 const int INF = 0x3f3f3f3f; 14 const int maxn=100000+5; 15 16 int p[15][15]; 17 int sum[maxn]; 18
int num[maxn]; 19 int x, k,cnt; 20 21 void init() //處於後5位的情況,i是枚舉,sum[i]存儲的是對應k下的值 22 { 23 cnt=0; 24 memset(sum,0,sizeof(sum)); 25 for(int i=1;i<100000;i++) 26 { 27 int tmp=i; 28 while(tmp) 29 { 30 sum[i]+=p[tmp%10][k]; 31 tmp/=10;
32 } 33 num[cnt++]=sum[i]-i; 34 } 35 sort(num,num+cnt); 36 } 37 38 void solve() //枚舉前5位的值,然後二分查找即可 39 { 40 ll ans=0; 41 for(int i=0;i<100000;i++) 42 { 43 ll tmp=sum[i]-(ll)i*100000; 44 int idx=lower_bound(num,num+cnt,x-tmp)-num; 45 while(num[idx]==x-tmp && idx<cnt) 46 { 47 ans++; 48 idx++; 49 } 50 } 51 printf("%lld\n",ans); 52 } 53 54 int main() 55 { 56 //freopen("in.txt","r",stdin); 57 for(int i=1;i<10;i++) //預處理i^j的值 58 { 59 p[i][0]=1; 60 for(int j=1;j<10;j++) 61 p[i][j]=p[i][j-1]*i; 62 } 63 int T; 64 int kase=0; 65 scanf("%d",&T); 66 while(T--) 67 { 68 printf("Case #%d: ",++kase); 69 scanf("%d%d",&x,&k); 70 init(); 71 solve(); 72 } 73 return 0; 74 }

HDU 5936 Difference(折半搜索(中途相遇法))