1. 程式人生 > >HDU - 6223 Infinite Fraction Path

HDU - 6223 Infinite Fraction Path

Infinite Fraction Path
題 意:輸入一個n,一個長度為n的串,串的字元都是0-9之間,下標為i的字元只能到下標為(i*i+1)%n的位置。問從從那個下標出發,能使路徑字串的字典序最大。
資料範圍:
n < = 2 e 6

n<=2e6
輸入樣例:

4
3
149
5
12345
7
3214567
9
261025520

輸出樣例:

Case #1: 999
Case #2: 53123
Case #3: 7166666
Case #4: 615015015

思路:開始直接寫了一發dfs,發現最差的複雜度是 n 2

n^2 頭有點鐵了,看題解,dfs+剪枝
+優先佇列維護。優先佇列每次都取第幾個數step較小的一個值如果step相同就取字元較大的一個值s[index]。剪枝怎麼剪呢?1.小於當前層的最大值的不需要加入佇列,2.同樣層,且在當前位置已經出現過了不需要加入佇列。還有一個坑點,那就是必須直接算當前層,假設第一層已經知道了,然後通過第一層取算下一層。這樣邏輯上是有問題的。
然後並不知道這個的複雜度是多少,玄學剪枝。歡迎留言告訴我複雜度是多少(lll¬ω¬)~

收穫:這個思維還是很厲害的,要經常複習。(lll¬ω¬)

銅牌題:讀題 + 思維

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<queue>
#include<cmath>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<11
#define IN freopen("input.txt","r",stdin)
#define mst(x,y) memset(x,y,sizeof(x));
#define debug(x) cout<< #x <<" = "<< (x) <<endl;
#define min(x,y) x>y?y:x
#define max(x,y) x>y?x:y
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef unsigned long long ull;
const int mod = 1e6+3;
const int INF = 0x3f3f3f3f;
const int LINF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5+5;
int n;
int d[maxn];
int sta[maxn];
bool vis[maxn];
char s[maxn];
struct node {
    ll index,step;
    bool operator< (const node &_p)const {
        if(step == _p.step)return s[index]<s[_p.index];
        return step>_p.step;
    }
};
priority_queue<node> que;
void init() {
    while(!que.empty())que.pop();
    mst(d,-1);
    mst(vis,false);
    mst(sta,0);
}
int main() {
    //IN;
    int t,Kase = 1;
    scanf("%d",&t);
    while(t--) {
        init();
        scanf("%d",&n);
        scanf("%s",s);
        int len = strlen(s);
        char temp = '0';
        for(int i=0; i<len; i++)temp = max(temp,s[i]);
        for(int i=0; i<len; i++) {
            if(temp == s[i]) {
                que.push(node{(ll)i,(ll)1});
            }
        }
        ll last = 1,top = 0;
        while(!que.empty()) {
            node q = que.top();
            que.pop();
            if(q.step!=last) {
                last = q.step;
                while(top)vis[sta[--top]]=false;
            }
            int to = (q.index*q.index+1)%n;
            if(q.step>n || vis[q.index] || d[q.step]>s[q.index]-'0') continue;
            vis[q.index] = true;
            sta[top++]=q.index;
            d[q.step]=s[q.index]-'0';
            que.push(node{to,q.step+1});
        }
        printf("Case #%d: ",Kase++);
        for(int i=1; i<=n; i++) {
            printf("%d",d[i]);
        }
        printf("\n");
    }
    return 0;
}