GDOI2016模擬8.8處理器

題目
你有一個微型處理器,處理器有N個寄存器,編號爲1到N,每個寄存器用二進制存儲一個32位無符號整數(取值範圍爲0到2^32-1)。存儲器能執行以下操作:

指令 描述 Example
1 K M 把寄存器K裏面的數字向右旋轉M位,再把結果寫進寄存器K。 00000000000000000010001111111011

→ (M = 1010) → 11111110110000000000000000001000

(十進制下: 9211 → (M = 10) → 4 273 995 784)
2 K L 把寄存器K和L中的值進行異或運算,結果輸出到系統總線中。 00000000000000000000001111000111

XOR 00000000000001111100000000000111

= 00000000000001111100001111000000

(十進制下: 967 XOR 507 911 = 508 864)

如果有多種解,輸出字典序最小的解(如果兩組解的前K-1個寄存器值相同,第K個寄存器不同,則第K個寄存器的值較小的解字典序更小)。

這題我們可以將每個寄存器的每一位抽出來考慮相互的關係,對於旋轉操作,我們可以維護起始指針位置來還原回去後一一對應考慮。

然後用並查集做。
由於會有後效性,而且不能保證字典序最小,我們不能通過一開始決定x屬於1或屬於0,但可以通過維護x與其並查集頂部位的數是否相同來做。

對於x和y間的關係,若x和y在同一個並查集裏,那麼若x與y不同,而x與並查集頂部相同,y與並查集頂部也相同,則輸出nema(還有x與y相同,同理可推)

若x和y在不同並查集裏,那麼我們通過x與y的關係,以及x與其並查集頂部的關係,和y與其並查集頂部的關係,推得將兩個並查集頂部合併時連邊的權值,若爲1,則說明兩個頂部不同,爲0則相同。(動手推一下)

這些權值在getfather時迭代加起來,得到x與頂部是否相同。(奇數爲不同,偶數爲相同)

最後求答案,從高位枚舉,看一下其所在並查集是否已確定,確定了的話,直接按限制得出,反之爲0,然後按限制強制將頂部賦值。

貼代碼

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
int n,m;
int fa[N*32][2],s[N];
long long help[32];
bool bz[N*32],ans[N*32];
bool p;
void pre(){
    help[0]=1;
    for (int i=1;i<32;i++)
        help[i]=help[i-1]+help[i-1];
}
int get(int x){
    int y;
    if (fa[x][0]==x)return x;
    y=fa[x][0];
    fa[x][0]=get(fa[x][0]);
    fa[x][1]=(fa[x][1]+fa[y][1])&1;
    return fa[x][0];
}
void init(){
    static int x,y,z;
    static long long v;
    scanf("%d %d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=32;j++)
            fa[(i-1)*32+j][0]=(i-1)*32+j;
    p=1;
    for (int i=1;i<=m;i++){
        scanf("%d %d %d",&x,&y,&z);
        if (x==1)
            s[y]=(s[y]+z)%32;
        else{
            scanf("%lld",&v);
            for (int i=0;i<32;i++){
                static bool e1,e2,e3;
                static int xx,yy;
                e1=v&help[i];
                xx=(y-1)*32+s[y]+1;
                yy=(z-1)*32+s[z]+1;
                get(xx);
                get(yy);
                e2=(fa[xx][1]!=fa[yy][1]);
                e3=(fa[xx][0]==fa[yy][0]);
                if (e3&&e2!=e1)p=0;
                else
                    if (!e3){
                        fa[fa[xx][0]][1]=(e2!=e1);
                        fa[fa[xx][0]][0]=fa[yy][0];
                    }
                s[y]=(s[y]+1)%32;
                s[z]=(s[z]+1)%32;
            }
        }   
    }
}
void write(){
    static int x;
    static long long y;
    if (!p)printf("-1");
    else
    for (int i=1;i<=n;i++){
        y=0;
        for (int j=32;j;j--){
            x=(i-1)*32+j;
            if (!bz[x]){
                get(x);
                if (bz[fa[x][0]])
                    ans[x]=(ans[fa[x][0]]^fa[x][1]);
                else
                    bz[fa[x][0]]=1,ans[fa[x][0]]=fa[x][1];
                bz[x]=1;
            }
            y+=ans[x]*help[j-1];
        }
        printf("%lld ",y);
    }
}
int main(){
    pre();
    init();
    write();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章