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

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
",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 }
原文地址:https://www.cnblogs.com/zyb993963526/p/7455125.html