今日小結:今天作了幾道分層最短路的題目和幾道最小生成樹的題目,而後給他們講了兩道題,晚上剩下的時候看了些\(tarjan\),割點那塊有點懵。node
洛谷P3831,洛谷P4568,洛谷P4822,洛谷P2939,洛谷P1265,洛谷P1318,洛谷P1547,洛谷P4018ios
SHOI2012 D2T1git
\(2046\) 年 \(OI\) 城的城市軌道交通建設終於所有竣工,因爲前期規劃周密,建成後的軌道交通網絡由\(2n\)條地鐵線路構成,組成了一個\(n\)縱\(n\)橫的交通網。以下圖所示,這\(2n\)條線路每條線路都包含\(n\)個車站,而每一個車站都在一組縱橫線路的交匯處。算法
出於建設成本的考慮,並不是每一個車站都可以進行站內換乘,可以進行站內換乘的地鐵站共有\(m\)個,在下圖中,標上方塊標記的車站爲換乘車站。已知地鐵運行 \(1\) 站須要 \(2\) 分鐘,而站內換乘須要步行 \(1\) 分鐘。\(Serenade\) 想要知道,在不中途出站的前提下,他從學校回家最快須要多少時間(等車時間忽略不計)。數組
輸入格式:網絡
第一行有兩個整數\(n,m\)。ide
接下去\(m\)行每行兩個整數\(x,y\),表示第\(x\)條橫向線路與第\(y\)條縱向線路的交測試
匯站是站內換乘站。ui
接下去一行是四個整數\(x_1,y_1,x_2,y_2\)。表示 \(Serenade\) 從學校回家時,在第 \(x_1\)條橫向線路與第\(y_1\)?條縱向線路的交匯站上車,在第\(x_2\)?條橫向線路與第\(y_2\)?條縱向線路的交匯站下車。spa
輸出格式:
輸出文件只有一行,即 \(Serenade\) 在合理選擇線路的狀況下,回家所須要的時間。若是 \(Serenade\) 沒法在不出站換乘的狀況下回家,請輸出\(-1\)。
輸入樣例#1:
2 1 1 2 1 1 2 2
輸出樣例#1:
5
輸入樣例#2:
6 9 2 1 2 5 3 2 4 4 5 2 5 6 6 1 6 3 6 4 1 1 4 6
輸出樣例#2:
27
輸入樣例#3:
6 10 2 1 2 5 3 2 4 4 5 2 5 6 6 1 6 3 6 4 6 6 1 1 4 6
輸出樣例#3:
26
對於 \(30\%\)的數據,\(n\le 50,m\le 1000\);
對於 \(60\%\)的數據,\(n\le 500,m\le 2000\);
對於 \(100\%\)的數據,\(n\le 20000,m\le 100000\);
代碼:
#include<cstdio> #include<algorithm> #include<cstring> #include<cctype> #include<queue> #define maxn 2000001 using namespace std; int n,m,head[maxn],num,dis[maxn]; inline int qread() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) num=num*10+c-'0';return num*f; } struct edge { int v,w,nxt; }e[maxn]; struct node { int x,y; bool operator < (const node &a) const {return y>a.y;} }; struct Edge { int x,y,id; }zrj[maxn]; inline void ct(int u, int v, int w) { e[++num].v=v; e[num].w=w; e[num].nxt=head[u]; head[u]=num; } inline void ist(int u, int v, int w) {ct(u,v,w);ct(v,u,w);} inline bool cmp1(Edge a, Edge b) { if(a.x==b.x) return a.y<b.y;return a.x<b.x; } inline bool cmp2(Edge a, Edge b) { if(a.y==b.y) return a.x<b.x;return a.y<b.y; } priority_queue<node>q; inline void dijkstra() { memset(dis,0x3f,sizeof(dis)); dis[m+1]=0;q.push((node){m+1,0}); while(!q.empty()) { int u=q.top().x,d=q.top().y; q.pop(); if(d!=dis[u]) continue; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; q.push((node){v,dis[v]}); } } } } int main() { n=qread(),m=qread(); for(int i=1;i<=m+2;++i) zrj[i].x=qread(),zrj[i].y=qread(),zrj[i].id=i; sort(zrj+1,zrj+m+3,cmp1); for(int i=1;i<m+2;++i) if(zrj[i].x==zrj[i+1].x) ist(zrj[i].id,zrj[i+1].id,2*(zrj[i+1].y-zrj[i].y)); sort(zrj+1,zrj+m+3,cmp2); for(int i=1;i<m+2;++i) if(zrj[i].y==zrj[i+1].y) ist(zrj[i].id+m+2,zrj[i+1].id+m+2,2*(zrj[i+1].x-zrj[i].x)); for(int i=1;i<=m;++i) ist(i,i+m+2,1); ist(m+1,m*2+3,0);ist(m+2,m*2+4,0); dijkstra(); printf("%d\n",dis[m+2]); return 0; }
\(Alice\)和\(Bob\)如今要乘飛機旅行,他們選擇了一家相對便宜的航空公司。該航空公司一共在\(n\)個城市設有業務,設這些城市分別標記爲\(0\)到\(n−1\),一共有\(m\)種航線,每種航線鏈接兩個城市,而且航線有必定的價格。
\(Alice\)和\(Bob\)如今要從一個城市沿着航線到達另外一個城市,途中能夠進行起色。航空公司對他們此次旅行也推出優惠,他們能夠免費在最多\(k\)種航線上搭乘飛機。那麼\(Alice\)和\(Bob\)此次出行最少花費多少?
輸入格式:
數據的第一行有三個整數,\(n,m,k\),分別表示城市數,航線數和免費乘坐次數。
第二行有兩個整數,\(s,t\),分別表示他們出行的起點城市編號和終點城市編號。
接下來有\(m\)行,每行三個整數,\(a,b,c\),表示存在一種航線,能從城市\(a\)到達城市\(b\),或從城市\(b\)到達城市\(a\),價格爲\(c\)。
輸出格式:
只有一行,包含一個整數,爲最少花費。
輸入樣例#1:
5 6 1 0 4 0 1 5 1 2 5 2 3 5 3 4 5 2 3 3 0 2 100
輸出樣例#1:
8
對於\(30\%\)的數據,\(2 \le n \le 50,1 \le m \le 300,k=0\);
對於\(50\%\)的數據,\(2 \le n \le 600,1 \le m \le 6000,0 \le k \le 1\);
對於\(100\%\)的數據,\(2 \le n \le 10000,1 \le m \le 50000,0 \le k \le 10\)
\(2018.12.10\) 增長一組 \(hack\) 數據
思路:一個明顯的分層最短路問題,就是創建\(n\)層圖,而後建原圖的映射邊,每一個點與它連向的點的映射點距離爲\(0\),以後跑\(dijkstra\),由於\(k\)次免費機會能夠不用完,因此從\(1\)到\(k\)取最大值就行了。
代碼:
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<cctype> #define maxn 5000001 using namespace std; int n,m,k,head[maxn],num,dis[maxn],s,t; inline int qread() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) num=num*10+c-'0';return num*f; } struct Edge { int v,w,nxt; }e[maxn]; struct node { int x,y; bool operator < (const node &a) const {return y>a.y;} }; inline void ct(int u, int v, int w) { e[++num].v=v; e[num].w=w; e[num].nxt=head[u]; head[u]=num; } priority_queue<node>q; inline void dijkstra() { memset(dis,0x3f,sizeof(dis)); dis[s+n*k]=0;q.push((node){s+n*k,0}); while(!q.empty()) { int u=q.top().x,d=q.top().y; q.pop(); if(d!=dis[u]) continue; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; q.push((node){v,dis[v]}); } } } } int main() { n=qread(),m=qread(),k=qread(),s=qread(),t=qread(); for(int i=1,u,v,w;i<=m;++i) { u=qread(),v=qread(),w=qread(); for(int j=0;j<=k;++j) { ct(u+j*n,v+j*n,w); ct(v+j*n,u+j*n,w); if(j) { ct(u+j*n,v+(j-1)*n,0); ct(v+j*n,u+(j-1)*n,0); } } } dijkstra(); int zrj=0x7fffffff; for(int i=0;i<=k;++i) zrj=min(zrj,dis[t+i*n]); printf("%d\n",zrj); return 0; }
「我要成爲魔法少女!」
「那麼,以靈魂爲代價,你但願獲得什麼?」
「我要將有關魔法和奇蹟的一切,封印於卡片之中„„」
在這個願望被實現之後的世界裏,人們享受着魔法卡片(\(SpellCard\),又名符卡)帶來的便捷。
如今,不須要立下契約也可使用魔法了!你還不來試一試?
好比,咱們在魔法百科全書(\(Encyclopedia of Spells\))裏用「\(freeze\)」做爲關鍵字來查詢,會有不少有趣的結果。
例如,咱們熟知的\(Cirno\),她的冰凍魔法固然會有對應的 \(SpellCard\) 了。 固然,更加使人驚訝的是,竟然有凍結時間的魔法,\(Cirno\) 的凍青蛙比起這些來真是小巫見大巫了。
這說明以前的世界中有不少魔法少女曾許下控制時間的願望,好比 \(Akemi Homura\)、\(Sakuya Izayoi\)、„„
固然,在本題中咱們並非要來研究歷史的,而是研究魔法的應用。
咱們考慮最簡單的旅行問題吧: 如今這個大陸上有 \(N\) 個城市,\(M\) 條雙向的道路。城市編號爲 \(1~N\),咱們在 \(1\) 號城市,須要到 \(N\) 號城市,怎樣才能最快地到達呢?
這不就是最短路問題嗎?咱們都知道能夠用 \(Dijkstra、Bellman-Ford、Floyd-Warshall\)等算法來解決。
如今,咱們一共有 K 張可使時間變慢 \(50\%\)的 \(SpellCard\),也就是說,在經過某條路徑時,咱們能夠選擇使用一張卡片,這樣,咱們經過這一條道路的時間 就能夠減小到原先的一半。須要注意的是:
你沒必要使用完全部的 \(SpellCard\)。
給定以上的信息,你的任務是:求出在可使用這不超過 \(K\) 張時間減速的 \(SpellCard\) 之情形下,從城市\(1\) 到城市\(N\)最少須要多長時間。
輸入格式:
第一行包含三個整數:\(N、M、K\)。
接下來 \(M\) 行,每行包含三個整數:\(A_i、B_i、Time_i\),表示存在一條 \(A_i\)與 \(B_i\)之間的雙向道路,在不使用 \(SpellCard\) 以前提下,經過它須要 \(Time_i\)的時間。
輸出格式:
輸出一個整數,表示從\(1\) 號城市到 \(N\)號城市的最小用時。
輸入樣例#1:
4 4 1 1 2 4 4 2 6 1 3 8 3 4 8
輸出樣例#1:
7
樣例解釋:
在不使用 \(SpellCard\) 時,最短路爲 \(1à2à4\),總時間爲 \(10\)。如今咱們可使用 \(1\) 次 \(SpellCard\),那麼咱們將經過 \(2à4\) 這條道路的時間減半,此時總時間爲\(7\)。
對於\(100\%\)的數據:\(1 ≤ K ≤ N ≤ 50,M ≤ 1000\)。
\(1≤ A_i,B_i ≤ N,2 ≤ Time_i ≤ 2000\)。
爲保證答案爲整數,保證全部的 \(Time_i\)均爲偶數。
全部數據中的無向圖保證無自環、重邊,且是連通的。
思路:仍是跟其餘的分層最短路題目同樣,只不過以前的\(k\)次免費的機會變成了\(k\)次免費縮小到一半的機會,那麼分層的時候咱們把邊權由\(0\)改成\(w/2\)就能夠了。
代碼:
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<cctype> #define maxn 5000001 using namespace std; int n,m,k,head[maxn],num,dis[maxn],s,t; inline int qread() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) num=num*10+c-'0';return num*f; } struct Edge { int v,w,nxt; }e[maxn]; struct node { int x,y; bool operator < (const node &a) const {return y>a.y;} }; inline void ct(int u, int v, int w) { e[++num].v=v; e[num].w=w; e[num].nxt=head[u]; head[u]=num; } priority_queue<node>q; inline void dijkstra() { memset(dis,0x3f,sizeof(dis)); dis[1+n*k]=0;q.push((node){1+n*k,0}); while(!q.empty()) { int u=q.top().x,d=q.top().y; q.pop(); if(d!=dis[u]) continue; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; q.push((node){v,dis[v]}); } } } } int main() { n=qread(),m=qread(),k=qread(); for(int i=1,u,v,w;i<=m;++i) { u=qread(),v=qread(),w=qread(); for(int j=0;j<=k;++j) { ct(u+j*n,v+j*n,w); ct(v+j*n,u+j*n,w); if(j) { ct(u+j*n,v+(j-1)*n,w/2); ct(v+j*n,u+(j-1)*n,w/2); } } } dijkstra(); int zrj=0x7fffffff; for(int i=0;i<=k;++i) zrj=min(zrj,dis[n+i*n]); printf("%d\n",zrj); return 0; }
約翰一共有\(N\))個牧場.由\(M\)條佈滿塵埃的小徑鏈接.小徑可 以雙向通行.天天早上約翰從牧場\(1\)出發到牧場\(N\)去給奶牛檢查身體.
經過每條小徑都須要消耗必定的時間.約翰打算升級其中\(K\)條小徑,使之成爲高 速公路.在高速公路上的通行幾乎是瞬間完成的,因此高速公路的通行時間爲\(0\).
請幫助約翰決定對哪些小徑進行升級,使他天天從\(1\)號牧場到第\(N\)號牧場所花的時間最短
Farmer John dutifully checks on the cows every day. He traverses some of the \(M (1 <= M <= 50,000)\) trails conveniently numbered \(1..M\) from pasture \(1\) all the way out to pasture \(N\) (a journey which is always possible for trail maps given in the test data). The \(N\) (\(1 <= N <= 10,000\)) pastures conveniently numbered \(1..N\) on Farmer John's farm are currently connected by bidirectional dirt trails. Each trail i connects pastures \(P1_i\) and \(P2_i\) (\(1 <= P1_i <= N; 1 <= P2_i <= N\)) and requires \(T_i\) (\(1 <= T_i <= 1,000,000\)) units of time to traverse.
He wants to revamp some of the trails on his farm to save time on his long journey. Specifically, he will choose \(K\) (\(1 <= K <= 20\)) trails to turn into highways, which will effectively reduce the trail's traversal time to \(0\). Help FJ decide which trails to revamp to minimize the resulting time of getting from pasture \(1\) to \(N\).
TIME LIMIT: \(2\) seconds
輸入格式:
Line \(1\): Three space-separated integers: \(N, M\), and \(K\)
Lines \(2..M+1\): Line \(i+1\) describes trail i with three space-separated integers: \(P1_i, P2_i\), and \(T_i\)
輸出格式:
輸入樣例#1:
4 4 1 1 2 10 2 4 10 1 3 1 3 4 100
輸出樣例#1:
1
\(K\) is \(1\); revamp trail \(3->4\) to take time \(0\) instead of \(100\). The new shortest path is \(1->3->4\), total traversal time now \(1\).
思路:依舊是分層最短路,此次的分層最短是的\(k\)是有\(k\)次能夠不花費任何代價去走一條路,那麼咱們把圖分爲\(n\)層,每條邊連向映射點與原來邊的起來的距離爲\(0\),而後跑\(dijkstra\),就作完了。
代碼:
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<cctype> #define maxn 5000001 using namespace std; int n,m,k,head[maxn],num,dis[maxn],s,t; inline int qread() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) num=num*10+c-'0';return num*f; } struct Edge { int v,w,nxt; }e[maxn]; struct node { int x,y; bool operator < (const node &a) const {return y>a.y;} }; inline void ct(int u, int v, int w) { e[++num].v=v; e[num].w=w; e[num].nxt=head[u]; head[u]=num; } priority_queue<node>q; inline void dijkstra() { memset(dis,0x3f,sizeof(dis)); dis[1+n*k]=0;q.push((node){1+n*k,0}); while(!q.empty()) { int u=q.top().x,d=q.top().y; q.pop(); if(d!=dis[u]) continue; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; q.push((node){v,dis[v]}); } } } } int main() { n=qread(),m=qread(),k=qread(); for(int i=1,u,v,w;i<=m;++i) { u=qread(),v=qread(),w=qread(); for(int j=0;j<=k;++j) { ct(u+j*n,v+j*n,w); ct(v+j*n,u+j*n,w); if(j) { ct(u+j*n,v+(j-1)*n,0); ct(v+j*n,u+(j-1)*n,0); } } } dijkstra(); int zrj=0x7fffffff; for(int i=0;i<=k;++i) zrj=min(zrj,dis[n+i*n]); printf("%d\n",zrj); return 0; }
某國有\(n\)個城市,它們互相之間沒有公路相通,所以交通十分不便。爲解決這一「行路難」的問題,政府決定修建公路。修建公路的任務由各城市共同完成。
修建工程分若干輪完成。在每一輪中,每一個城市選擇一個與它最近的城市,申請修建通往該城市的公路。政府負責審批這些申請以決定是否贊成修建。
政府審批的規則以下:
\((1)\)若是兩個或以上城市申請修建同一條公路,則讓它們共同修建;
\((2)\)若是三個或以上的城市申請修建的公路成環。以下圖,\(A\)申請修建公路\(AB\),\(B\)申請修建公路\(BC\),\(C\)申請修建公路\(CA\)。則政府將否決其中最短的一條公路的修建申請;
\((3)\)其餘狀況的申請一概贊成。
一輪修建結束後,可能會有若干城市能夠經過公路直接或間接相連。這些能夠互相:連通的城市即組成「城市聯盟」。在下一輪修建中,每一個「城市聯盟」將被看做一個城市,發揮一個城市的做用。
當全部城市被組合成一個「城市聯盟」時,修建工程也就完成了。
你的任務是根據城市的分佈和前面講到的規則,計算出將要修建的公路總長度。
輸入格式:
第一行一個整數\(n\),表示城市的數量。(\(n≤5000\))
如下\(n\)行,每行兩個整數\(x\)和\(y\),表示一個城市的座標。(\(-1000000≤x,y≤1000000\))
輸出格式:
一個實數,四捨五入保留兩位小數,表示公路總長。(保證有唯一解)
輸入樣例#1:
4 0 0 1 2 -1 2 0 4
輸出樣例#1:
6.47
修建的公路如圖所示:
思路:第一眼,咱們思路是對每兩個點求出它們之間的距離,而後建邊,跑\(Kruskal\),可是看了數據範圍後放棄了,由於\(m\)太大,不能用\(Kruskal\),因而就用\(prim\),可是數組好像又開不下,那就乾脆從\(1\)開始擴展,先\(O(n)\)處理出\(1\)號點到其它全部點的距離,而後再跑\(prim\),由於保證必定有解,跑完之間輸出答案就好了。
代碼:
#include<cstdio> #include<cstring> #include<cmath> #define maxn 5007 #define dl double using namespace std; int n,m,x[maxn],y[maxn]; dl dis[maxn],ans,minn,num; bool vis[maxn]; inline dl jl(int i,int j) { return sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j])); } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d%d",&x[i],&y[i]); for(int i=2;i<=n;++i) dis[i]=jl(1,i); dis[1]=0,vis[1]=1; for(int i=1;i<n;++i) { minn=1e9; int k=0; for(int j=1;j<=n;++j) if(!vis[j]&&minn>dis[j]) minn=dis[j],k=j; vis[k]=1,ans+=minn; for(int j=1;j<=n;++j) { num=jl(k,j); if(!vis[j]&&dis[j]>num) dis[j]=num; } } printf("%0.2lf",ans); return 0; }
一組正整數,分別表示由正方體疊起的柱子的高度。若某高度值爲\(x\),表示由\(x\)個正立方的方塊迭起(以下圖,\(0<=x<=5000\))。找出全部可能積水的地方(圖中藍色部分),統計它們可能積水的面積總和(計算的是圖中的橫截面積。一個立方體的位置,爲一個單位面積)。
如圖:柱子高度變化爲 0 1 0 2 1 2 0 0 2 0
圖中藍色部分爲積水面積,共有\(6\)個單位面積積水。
輸入格式:
兩行,第一行n,表示有n個數(\(3<=n<=10000\))。第2行連續n個數表示依次由正方體迭起的高度,保證首尾爲\(0\)。
輸出格式:
一個數,可能積水的面積。
輸入樣例#1:
10 0 1 0 2 1 2 0 0 2 0
輸出樣例#1:
6
思路:挺水的一道題,可是第一遍寫仍是錯了,我覺得是今年noip T1,然而想錯了,沒認真讀題,這個題其實就是看看一個位置的左右高度有不有差值,有的話就加上這個差值。
代碼:
#include<iostream> #include<cstdio> #define maxn 10001 using namespace std; int n,l[maxn],r[maxn],a[maxn],ans; int main() { scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); l[i]=max(l[i-1],a[i]); } for(int i=n;i>=1;--i) r[i]=max(r[i+1],a[i]); for(int i=1;i<=n;++i) if(min(l[i],r[i])-a[i]>0) ans+=min(l[i],r[i])-a[i]; printf("%d\n",ans); return 0; }
奶牛愛乾草
\(Bessie\) 計劃調查\(N (2 <= N <= 2,000)\)個農場的乾草狀況,它從\(1\)號農場出發。農場之間總共有M \((1 <= M <= 10,000)\)條雙向道路,全部道路的總長度不超過\(1,000,000,000\)。有些農場之間存在着多條道路,全部的農場之間都是連通的。
\(Bessie\)但願計算出該圖中最小生成樹中的最長邊的長度。
輸入格式:
兩個整數\(N\)和\(M\)。
接下來\(M\)行,每行三個用空格隔開的整數\(A_i, B_i\)和\(L_i\),表示\(A_i\)和 \(B_i\)之間有一條道路長度爲\(L_i\)。
輸出格式:
一個整數,表示最小生成樹中的最長邊的長度。
輸入樣例#1:
3 3 1 2 23 2 3 1000 1 3 43
輸出樣例#1:
43
思路:用來練最小生成樹的,能夠說是一道比較水的題目,能夠直接跑\(Kruskal\),而且每次向MST中加一條邊時就更新最大值,最後輸出最大值。而後……就作完了。
代碼:
#include<algorithm> #include<cstdio> #define maxn 10001 using namespace std; int n,maxx,k,m,fa[2001]; struct node { int u,v,w; }e[maxn]; inline bool cmp(node a, node b) {return a.w<b.w;} inline int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);} inline void uni(int x,int y) {x=find(x),y=find(y);fa[y]=x;} int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); sort(e+1,e+1+m,cmp); for(int i=1;i<=n;++i) fa[i]=i; for(int i=1;i<=m;++i) { if(find(e[i].u)!=find(e[i].v)) { maxx=max(maxx,e[i].w); uni(e[i].u,e[i].v); k++; } if(k==n-1) break; } printf("%d\n",maxx); return 0; }
\(Roy\)和\(October\)兩人在玩一個取石子的遊戲。
遊戲規則是這樣的:共有\(n\)個石子,兩人每次都只能取\(p^k\)個(\(p\)爲質數,\(k\)爲天然數,且\(p^k\)小於等於當前剩餘石子數),誰取走最後一個石子,誰就贏了。
如今\(October\)先取,問她有沒有必勝策略。
若她有必勝策略,輸出一行"\(October wins!\)";不然輸出一行"\(Roy wins!\)"。
輸入格式:
第一行一個正整數T,表示測試點組數。
第\(2\)行~第\((T+1)\)行,一行一個正整數\(n\),表示石子個數。
輸出格式:
\(T\)行,每行分別爲"\(October wins!\)"或"\(Roy wins!\)"。
輸入樣例#1:
3 4 9 14
輸出樣例#1:
October wins! October wins! October wins!
對於\(30\%\)的數據,\(1<=n<=30\);
對於\(60\%\)的數據,\(1<=n<=1,000,000\);
對於\(100\%\)的數據,\(1<=n<=50,000,000,1<=T<=100,000\)。
(改編題)
思路:被洛谷標籤給騙了,不知道爲何這道題的標籤是\(prim\),原本是想練最小生成樹,看數據範圍,根本不可作,並且……也無法建邊啊,洛谷標籤真的是……不過點進來了,就作作吧,發現這其實就是個打表題,若是輸入的\(n\)模\(6\)值爲\(0\),就是先手必敗態,不然爲先手必勝態。
代碼:
#include<cstdio> using namespace std; int t,n; int main() { scanf("%d",&t); while(t--) { scanf("%d",&n); if(n%6) printf("October wins!\n"); else printf("Roy wins!\n"); } return 0; }