【题目描述】

Description

神犇最近闲来无事,于是就思考哲学,研究数字之美。在神犇看来,如果一个数的各位能够被分成两个集合,而且这两个集合里的数的和相等,那么这个数就是优美的(具体原因就只有神犇才知道了)。现在神犇在思考另一个问题,在区间[a,b]中有多少个数是优美的?这个问题对于神犇来说很简单,相信对于你来说也不难。 
Input

输入只有一行,包含两个整数a和b。 
Output

输出只有一行,包含一个整数,代表区间[a,b]中优美的数的个数。

Sample Input

1 11 
Sample Output


HINT

1<=A<=B<=10^9

【思路】

  • 对于每个数x,可以log(x)复杂度内(二进制背包问题,状压,long long f初始化为1,f|=f<<d,d是x的每一位数)求出这个数是不是完美数
  • 对于[a,b]内有多少个完美数,可以由前缀和sum[a]-sum[b-1]得出
  • 考虑到a=1,b=1e9时不能在线算,所以要打表预处理
  • 考虑到打表要打1e9,显然不允许
  • 因为要求的是前缀和,所以我们可以分块求和,整块的由表得出,最右边不在整块的暴力(前面已经说了单个复杂度很小)
  • 综合考虑时间和空间,1e9个数分成1e3块(要考虑到编译超时的问题?),空间1e3可以,时间1e6logx也可以

 【AC】

http://blog.csdn.net/PoPoQQQ/article/details/41551913

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<string>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 
10 using namespace std;
11 typedef long long ll;
12 const int maxn=1e9;
13 int table[1003];
14 bool check(int x)
15 {
16     int sum=0;
17     for(int i=x;i;i/=10)
18     {
19         sum+=i%10;
20     }
21     if(sum&1) return false;
22     sum>>=1;
23     ll f=1ll;
24     for(int i=x;i;i/=10)
25     {
26         f|=f<<(i%10);
27     }
28     return f&(1<<sum);
29 }
30 int main()
31 {
32     freopen("data.txt","w",stdout);
33     memset(table,0,sizeof(table));
34     int cnt=1;
35     for(int i=1;i<=maxn;i++)
36     {
37         if(check(i))
38         {
39             table[cnt]++;
40         }
41         if(i%1000000==0)
42         {
43             cnt++;
44             table[cnt]=table[cnt-1];
45         }
46     }
47     for(int i=1;i<=1000;i++)
48     {
49         printf("%d,",table[i]);
50     }
51     return 0;
52 }
本地打表

相关文章: