1 //Result:2012-08-12 13:44:40 Accepted 4351 812MS 11016K 3495 B C++ Wizmann
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <iostream>
6 #include <algorithm>
7
8 using namespace std;
9
10 #define print(x) cout<<x<<endl
11 #define input(x) cin>>x
12 #define SIZE 100100
13 #define FORCE 1024
14
15 inline int left(int x){return (x<<1)+1;}
16 inline int right(int x){return (x<<1)+2;}
17
18 struct node
19 {
20 int l,r,val;
21 int now,lson,rson;
22 node(){}
23 node(int il,int ir)
24 {
25 l=il;r=ir;
26 val=now=lson=rson=0;
27 }
28 inline void init(int ival)
29 {
30 val=now=lson=rson=(1<<ival);
31 }
32 inline int getmid(){return (l+r)>>1;}
33 inline int equal(int il,int ir){return l==il&&r==ir;}
34 inline int has_next(){return l!=r;}
35 };
36
37 struct result
38 {
39 int val,now,lson,rson;
40 result(){}
41 result(int ival,int inow,int ilson,int irson)
42 {
43 val=ival;
44 now=inow;
45 lson=ilson;
46 rson=irson;
47 }
48 };
49
50 node stree[SIZE*3];
51 int n;
52 int k[SIZE];
53 int mp[FORCE+10][FORCE+10];
54 const int ROOT=0;
55
56 void init()
57 {
58 for(int i=0;i<FORCE;i++)
59 {
60 for(int j=0;j<FORCE;j++)
61 {
62 for(int a=0;a<=9;a++) if(i&(1<<a))
63 {
64 for(int b=0;b<=9;b++) if(j&(1<<b))
65 {
66 int val=(a+b-1)%9+1;
67 mp[i][j]|=(1<<val);
68 }
69 }
70 }
71 }
72 }
73
74 void stree_init(int l,int r,int pos=ROOT)
75 {
76 stree[pos]=node(l,r);
77 if(l==r) stree[pos].init(k[l]);
78 else if(l<r)
79 {
80 int mid=(l+r)>>1;
81 stree_init(l,mid,left(pos));
82 stree_init(mid+1,r,right(pos));
83
84 stree[pos].val=mp[stree[left(pos)].val][stree[right(pos)].val];
85 stree[pos].lson=stree[left(pos)].lson \
86 | mp[stree[left(pos)].val][stree[right(pos)].lson];
87 stree[pos].rson=stree[right(pos)].rson \
88 | mp[stree[right(pos)].val][stree[left(pos)].rson];
89 stree[pos].now=stree[left(pos)].now \
90 | stree[right(pos)].now \
91 | mp[stree[left(pos)].rson][stree[right(pos)].lson];
92 }
93 }
94
95 result stree_query(int l,int r,int pos=ROOT)
96 {
97 if(stree[pos].equal(l,r))
98 {
99 return result(stree[pos].val,stree[pos].now,stree[pos].lson,stree[pos].rson);
100 }
101 else
102 {
103 int mid=stree[pos].getmid();
104 if(r<=mid) return stree_query(l,r,left(pos));
105 else if(l>mid) return stree_query(l,r,right(pos));
106 else
107 {
108 result a=stree_query(l,mid,left(pos));
109 result b=stree_query(mid+1,r,right(pos));
110
111 int val=mp[a.val][b.val];
112 //val代表[l,r]区间的DigitalRoot
113 //mp[a.val][b.val],由于a.val和b.val都只有一个"1"位,所以mp[a.val][b.val]==DigitalRoot(a+b),也只有一位
114 int lson=a.lson | mp[a.val][b.lson];
115 //lson是指[l,r]区间的前辍,由a(左边)的lson与a.val与b.lson的和组成
116 int rson=b.rson | mp[a.rson][b.val];
117 //同上
118 int now = a.now | b.now | mp[a.rson][b.lson];
119 //now代表当前区间能表示的DigitalRoot的种类数
120 //a.now | b.now 父节点是继承子节点的可行值(这个好理解)
121 //mp[a.rson][b.lson]是指在[l,r]的中点mid处,[...mid][mid...]这种类型的合并
122
123 return result(val,now,lson,rson);
124 }
125 }
126 }
127
128
129 int main()
130 {
131
132 int T,a,b,q;
133 input(T);
134 init();
135 int res[10];
136 int cas=1;
137 while(T--)
138 {
139 printf("Case #%d:\n",cas++);
140 input(n);
141 for(int i=1;i<=n;i++)
142 {
143 scanf("%d",&a);
144 k[i]=(a-1)%9+1;
145 }
146 stree_init(1,n);
147 input(q);
148 while(q--)
149 {
150 scanf("%d%d",&a,&b);
151 result r=stree_query(a,b);
152 int ptr=0,val=9;
153 memset(res,-1,sizeof(res));
154 while(ptr<5 && val>=0)
155 {
156 if(r.now & (1<<val))
157 {
158 res[ptr++]=val;
159 }
160 val--;
161 }
162 for(int i=0;i<5;i++)
163 {
164 if(i) printf(" ");
165 printf("%d",res[i]);
166 }
167 puts("");
168 }
169 if(T) puts("");
170 }
171 return 0;
172 }