【2015ZUFE新生赛网络同步赛M】【DP 打表 二分】GW I (3) 暴力预处理+分类打表二分查找
2015-12-07 12:21
549 查看
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} int casenum,casei; const int TOP=1e7; int f[TOP+10]; vector<int>a[10]; vector<int>::iterator lft,rgt; inline int cnt(int x) { int p=0; int odd=0; int even=0; while(x) { ++p; if(p&1)odd+=x%10; else even+=x%10; x/=10; } return odd*even; } int st[]={1,10,100,1000,10000,100000}; int ed[]={9,99,999,9999,99999,999999}; int w[TOP/10+10][2]; int even,odd; void table() { for(int i=0;i<10;++i) { w[i][1]=i; f[i]=i; a[i].push_back(i); } for(int bit=0;bit<=5;++bit) { for(int i=st[bit];i<=ed[bit];++i) { int bef=i*10; for(int j=0;j<10;++j) { int now=bef+j; if(bit<5) { w[now][0]=w[i][1]; w[now][1]=w[i][0]+j; f[now]=f[w[now][0]*w[now][1]]; } else { even=w[i][1]; odd=w[i][0]+j; f[now]=f[even*odd]; } a[f[now]].push_back(now); } } } f[10000000]=0; a[0].push_back(10000000); } int main() { table(); scanf("%d",&casenum); for(casei=1;casei<=casenum;++casei) { int l,r,x; scanf("%d%d%d",&l,&r,&x); if(x>=10)puts("0"); else { lft=lower_bound(a[x].begin(),a[x].end(),l); rgt=upper_bound(a[x].begin(),a[x].end(),r); printf("%d\n",rgt-lft); } } return 0; } /* 【trick&&吐槽】 暴力出奇迹呀!分情况打表+二分真是好技巧哇! 评测机一变,我这种做法就大概是最优解了!O(1e8)的算法再也没法AC了呢! 【题意】 定义f(x)为—— if(x十进制下奇数位置数值和*x十进制下偶数位置数值和为个位数w,那么return w) else return f(w); 然后有T(1000)组询问。 对于每组询问,问你[0<=l<=r<=1e7]的区间范围内,有多少个数的f()权值为x。 【类型】 暴力 二分 【分析】 首先,显然x的取值范围是[0,9]。 所以,如果x不是[0,9],直接返回0. 然后,我们发现—— 我们可以用O(n)的时间算出[0~n]的f()值, 然后,我们无法记录x==0~9条件下的所有前缀和,因为数据范围太大会爆空间。 然而,这些数的总数也不过只有1e7个,对于f(x)==w,我们把w push_back到vector(x)中 这样对于一个查询区间[l,r],我们可以二分查询>=l和>r的第一个数的下标,两者减一下就是答案啦。 【时间复杂度&&优化】 O(n*k+Tlog()) 1,这题数字拆分的复杂度有些大,我们可以通过DP优化 2,我们用数组代替vector的话,时间效率也会大大提高。 */
相关文章推荐
- 快速排序里的学问:从猜数字开始
- HDU 4898 The Revenge of the Princess’ Knight ( 2014 Multi-University Training Contest 4 )
- Search Insert Position,Search for a Range,Pow(x, n),Sqrt(x)
- Find Minimum in Rotated Sorted Array II
- [LeetCode] Sqrt(x)
- [LeetCode] Pow(x, n)
- [LeetCode] Search Insert Position
- [LeetCode] Search for a Range
- [LeetCode] Search in Rotated Sorted Array
- PAT 1057 Stack (30)
- int sqrt(int x)
- Pow(x, n)
- Find Minimum in Rotated Sorted Array
- Divide Two Integers
- acm解题报告 HDU 2141 Can you find it?
- acm解题报告 HDU 2199 Can you solve this equation?
- acm解题报告 HDU 2899 Strange fuction
- acm解题报告 HDU 1969 Pie
- acm解题报告 HDU 1061 Rightmost Digit
- acm解题报告 POJ 2366 Sacrament of the sum