[vijos1162]波浪数
题目链接:https://www.vijos.org/p/1162
这题的解法我觉得可能是模拟吧,但是题的分类又是构造QAQ。。。。。
不是很懂,所以我们把这个方法叫做奇技淫巧吧
这题的暴力思路就是针对x到y这个范围里的每一个数进行判断,可以就输出
但是很容易看出,这个暴力会超时
所以就有了奇技淫巧
【思路】
我们预处理出范围内所有波浪数的波浪重数
这些波浪数我们可以主动去构造,这题中的波浪数其实拆开就是两个数字构成的,所有只需要枚举奇数位的i,和偶数位的j,i不能为0,然后最大为进制数-1
然后我们处理一下输入的范围x,y在p进制下的位数,并通过我们枚举的i,j和进制p构造位数在x,y之间的p进制数,接着把这个数转换成十进制,让这个波浪数的重数在十进制状态下+1,最后再十进制下枚举x,y之间的所有数,如果重数等于输入的s,就输出这个数
这个题的代码也不难,非常容易看懂滴
1 #include<cstdio>
2 #include<cstring>
3 #include<iostream>
4 #include<cstdlib>
5 #include<cmath>
6 #include<algorithm>
7 #include<queue>
8 #define maxn 10000005
9 using namespace std;
10
11 int num[maxn],ja,jb,x,y,s;
12
13 int length(int n,int p){//数字n在p进制下的长度
14 int cnt=0;
15 while(n){
16 n/=p;cnt++;
17 }return cnt;
18 }
19
20 int make(int a,int b,int len,int p){
21 int now=0;
22 for(int i=1;i<=len;i++){
23 if(i&1)now=now*p+a;
24 else now=now*p+b;
25 }return now;//转成10进制
26 }
27
28 void work(int p){
29 int l=length(x,p),r=length(y,p);
30 for(int i=1;i<p;i++){//首位不为0
31 for(int j=0;j<p;j++){
32 if(i!=j){//波浪数的条件
33 for(int k=l;k<=r;k++){
34 int sum=make(i,j,k,p);
35 //构造波浪数并转换成十进制sum
36 if(sum>=x&&sum<=y)num[sum]++;
37 }
38 }
39 }
40 }
41
42 }
43
44 int main(){
45 scanf("%d%d%d%d%d",&ja,&jb,&x,&y,&s);
46 for(int i=ja;i<=jb;i++){
47 work(i);
48 }
49 for(int i=x;i<=y;i++){
50 if(num[i]==s){
51 printf("%d\n",i);
52 }
53 }
54 }
【总结】
遇见一看数据范围就很暴力的题,可以换角度下手,要么反向操作,或者预处理,或者构造满足条件的数