题目大意:
有$n(nleq 150,000)$个编号为$0_n-1$格子,每个格子有一个权值$w_i(0leq w_ileq 9)$。从任意一个点出发,按照一定的规则进行跳转。设当前的格子为$i$,下一步跳转到$(i^2+1)mod n$的位置上。连续跳转$n$次,问最后经过格子的权值组成的串,字典序最大的是多少。
思路:
BFS剪枝。
每次把当前层最大的加入队列,然后再把下一层也加入队列。
一个剪枝是把小于当前层最大值的去掉,另一个剪枝是把同一层访问多次的点只保留一个。
1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 typedef long long int64; 5 inline int getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 inline int getdigit() { 13 register char ch; 14 while(!isdigit(ch=getchar())); 15 return ch^'0'; 16 } 17 const int N=150000; 18 int a[N],max[N],vis[N]; 19 struct Node { 20 int pos,dep; 21 }; 22 std::queue<Node> q; 23 int main() { 24 const int T=getint(); 25 for(register int i=1;i<=T;i++) { 26 printf("Case #%d: ",i); 27 const int n=getint(); 28 bool same=true; 29 for(register int i=0;i<n;i++) { 30 a[i]=getdigit(); 31 max[i]=vis[i]=0; 32 } 33 for(register int i=1;i<n;i++) { 34 if(a[i]!=a[i-1]) same=false; 35 } 36 if(same) { 37 for(register int i=0;i<n;i++) { 38 putchar(a[i]^'0'); 39 } 40 putchar(' '); 41 return 0; 42 } 43 for(register int i=0;i<n;i++) { 44 if(a[i]>=max[0]) { 45 max[0]=a[i]; 46 q.push((Node){i,0}); 47 } 48 } 49 while(!q.empty()) { 50 const int pos=q.front().pos,dep=q.front().dep; 51 q.pop(); 52 if(a[pos]<max[dep]||dep+1==n) continue; 53 if(a[((int64)pos*pos+1)%n]>=max[dep+1]&&vis[((int64)pos*pos+1)%n]!=dep+1) { 54 vis[((int64)pos*pos+1)%n]=dep+1; 55 max[dep+1]=a[((int64)pos*pos+1)%n]; 56 q.push((Node){((int64)pos*pos+1)%n,dep+1}); 57 } 58 } 59 for(register int i=0;i<n;i++) { 60 putchar(max[i]^'0'); 61 } 62 putchar(' '); 63 } 64 return 0; 65 }