【题目描述】
Description
神犇最近闲来无事,于是就思考哲学,研究数字之美。在神犇看来,如果一个数的各位能够被分成两个集合,而且这两个集合里的数的和相等,那么这个数就是优美的(具体原因就只有神犇才知道了)。现在神犇在思考另一个问题,在区间[a,b]中有多少个数是优美的?这个问题对于神犇来说很简单,相信对于你来说也不难。
Input
输入只有一行,包含两个整数a和b。
Output
输出只有一行,包含一个整数,代表区间[a,b]中优美的数的个数。
Sample Input
1 11
Sample Output
1
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 }