日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【20161109】noip模拟赛

發布時間:2025/7/14 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【20161109】noip模拟赛 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.Game

【題目描述】

明明和亮亮在玩一個游戲。桌面上一行有n個格子,一些格子中放著棋子。明明和亮亮輪流選擇如下方式中的一種移動棋子(圖示中o表示棋子,*表示空著的格子):

1)?當一枚棋子的右邊是空格子的話,可以將這枚棋子像右移動一格。

**o*** ????????-> ??????????***o**

2)?當一枚棋子的右邊連續兩個都有棋子,并且這個棋子往右邊數第3格沒有棋子,那么可以將這個棋子可以跳過去那兩個棋子

**ooo* ???????-> ??????????***oo*

當任何一枚棋子到達最右邊的格子時,這枚棋子自動消失。當一方不能移動時,這方輸。假設明明和亮亮都采取最優策略,明明先走,誰將取勝?

?

【輸入數據】

第一行一個整數T表示數據組數, 0 < T < 10。

之后T組數據,每組兩行,第一行n 表示格子個數,第二行n個字符表示每個格子的情況,o表示有棋子,*表示空著。

?

【輸出數據】

對于每組數據一個輸出,M表示明明贏,L表示亮亮贏。

?

【樣例輸入】

4

2

*o

5

*o***

6

**o**o

14

*o***ooo**oo**

?

【樣例輸出】

L

M

M

L

【數據范圍】

0 <T < 10

對于50%的數據, n < 20。

對于100%的數據, n < 1000。?


第一題就博弈。。跪跪跪。。

真心不會博弈。。今晚好好重學一遍。。

看題解好像很好理解???


Game解題報告

?

對于前50%的數據,由于n<20,整個棋盤的狀態個數 < 2^20。 由于狀態數有限,我們可以采取記憶化搜索的辦法來實現。

但對于100%的數據,n的最大可能值達到999,記憶化搜索就不怎么可行了。其實本題有一個更簡單的做法:

考慮每個棋子到最右邊格子的距離。把所有棋子這樣的距離的總和計為s。我們發現不管選擇兩種操作中的一種操作,每走一步,s的奇偶性都會發生一次變化。所以說,如果第一次輪到明明時,s是奇數,那么每次輪到明明時s都是奇數。而當s是奇數時,s肯定>0,這時明明總可以走最右邊的棋子。也就是說當s為奇數時,總有棋子可以走。所以說,一開始若s為奇數,則明明必勝。同理,若一開始s為偶數,則當亮亮走的時候s總是奇數,所以明明必敗。

?


?

貼個代碼:

?

1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 const int N=25,M=1<<21; 8 int n,f[2][M],a[N],b[N]; 9 char c[N],cc[N]; 10 11 int dfs(int x,int s) 12 { 13 if((s&1)!=0) s--; 14 if(f[x][s]!=-1) return f[x][s]; 15 int ss,ans=0; 16 for(int i=0;i<n;i++) 17 { 18 if((s&(1<<i))!=0 && (i-1>=0 && (s&(1<<(i-1)))==0)) 19 { 20 ss=s-(1<<i)+(1<<(i-1)); 21 if(dfs(1-x,ss)==0) ans=1; 22 } 23 if((s&(1<<i))!=0 && (i-1>=0 && (s&(1<<(i-1)))!=0) && (i-2>=0 && (s&(1<<(i-2)))!=0) && (i-3>=0 && (s&(1<<(i-3)))==0)) 24 { 25 ss=s-(1<<i)+(1<<(i-3)); 26 if(dfs(1-x,ss)==0) ans=1; 27 } 28 } 29 f[x][s]=ans; 30 // printf("f %d %d = %d\n",x,s,ans); 31 return ans; 32 } 33 34 void solve1() 35 { 36 scanf("%s",c); 37 memset(f,-1,sizeof(f)); 38 f[0][0]=f[1][0]=0; 39 int x=0; 40 for(int i=0;i<n;i++) 41 { 42 if(c[i]=='o') x|=(1<<(n-1-i)); 43 } 44 // printf("x = %d\n",x); 45 if(dfs(0,x)==1) printf("M\n"); 46 else printf("L\n"); 47 } 48 49 void solve2() 50 { 51 scanf("%s",c+1); 52 int sum=0; 53 for(int i=1;i<=n;i++) 54 { 55 if(c[i]=='o') sum+=n-i; 56 } 57 if(sum%2==0) printf("L\n"); 58 else printf("M\n"); 59 } 60 61 int main() 62 { 63 // freopen("a.in","r",stdin); 64 freopen("game.in","r",stdin); 65 freopen("game.out","w",stdout); 66 int T,x; 67 scanf("%d",&T); 68 while(T--) 69 { 70 scanf("%d",&n); 71 if(n<=20) solve1(); 72 else solve2(); 73 } 74 return 0; 75 } View Code

?


?

?

?

2.Walk

?

【題目描述】

?

有一塊n *n 的土地上,明明和亮亮站在(1,1)處。每塊地上寫有一個數字a(i, j)。現在他們決定玩一個游戲,每一秒鐘,他們倆走向相鄰且坐標變大的格子(從(x,y)到(x+1,y)或者從(x,y)到(x,y+1)),他們倆可以按照不同方式來走,最后經過2n-1步到達(n,n)處。明明和亮亮每一秒鐘計算他們站的兩個位置上數字的差的絕對值,他們希望這些差值的和最大,請問這個最大的和是多少?

?

?

?

【輸入數據】

?

第一行一個正整數n。

?

后面n行,每行n個整數,分別表示每塊地上的數字。

?

?

?

【輸出數據】

?

一個整數,表示最大的差值的和。

?

?

?

【樣例輸入】

?

4

?

1 2 3 4

?

1 5 3 2

?

8 1 3 4

?

3 2 1 5

?

?

?

【樣例輸出】

?

13

?

【數據范圍】

?

n <= 100, 每塊地上的數字的絕對值不超過300。


?

?

?

沒什么好說的。就直接dp,f[i][j][k]表示走了i步,第一個人的橫坐標是j,第二個人的橫坐標是k。

通過走了i步可以算出縱坐標。

第一維只開了100又跪了。。

1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 const int N=210; 8 int n,a[N][N],f[N][N][N]; 9 int dx[2]={0,1}; 10 int dy[2]={1,0}; 11 12 int myabs(int x){return x>0 ? x:-x;} 13 int minn(int x,int y){return x<y ? x:y;} 14 int maxx(int x,int y){return x>y ? x:y;} 15 16 int main() 17 { 18 // freopen("a.in","r",stdin); 19 freopen("walk.in","r",stdin); 20 freopen("walk.out","w",stdout); 21 scanf("%d",&n); 22 for(int i=0;i<n;i++) 23 for(int j=0;j<n;j++) 24 scanf("%d",&a[i][j]); 25 memset(f,-1,sizeof(f)); 26 f[0][0][0]=0; 27 int x1,y1,x2,y2,xx1,yy1,xx2,yy2; 28 for(int i=0;i<=2*n-2;i++) 29 for(int j=0;j<n;j++) 30 for(int k=0;k<n;k++) 31 { 32 if(f[i][j][k]==-1) continue; 33 // printf("f %d %d %d = %d\n",i,j,k,f[i][j][k]); 34 x1=j;y1=i-j; 35 x2=k;y2=i-k; 36 for(int ii=0;ii<=1;ii++) 37 for(int jj=0;jj<=1;jj++) 38 { 39 xx1=x1+dx[ii];yy1=y1+dy[ii]; 40 xx2=x2+dx[jj];yy2=y2+dy[jj]; 41 if(xx1>=n || yy1>=n || xx2>=n || yy2>=n) continue; 42 f[i+1][xx1][xx2]=maxx(f[i+1][xx1][xx2],f[i][x1][x2]+myabs(a[xx1][yy1]-a[xx2][yy2])); 43 } 44 } 45 printf("%d\n",f[2*n-2][n-1][n-1]); 46 return 0; 47 } View Code

3. Trip

【題目描述】

小朋友們出去郊游,明明和亮亮負責在草地上開一個篝火晚會。這個草地你可以認為是又 N * M 塊單位長度為1的小正方形的草組成。

顯然有的地方草長的好,有的地方長的不好,坐在上面顯然舒服度是不一樣的,于是每一塊草都有一個舒服度 F。

現在明明和亮亮要選定一個 a*b 的草場作為晚會的地點,小朋友們就坐在上面,顯然他希望小朋友們坐的最舒服!

不過別急,篝火晚會怎么能少了篝火呢,篝火需要占用 c*d 的草地,當然,篝火必須嚴格放置在選定的草地的內部,也就是說,篝火的邊界不能和選定操場的邊界有公共部分,不然學生們怎么圍著篝火開晚會呢?

給定 N*M 大草地每一塊的舒服度,尋找一個 a*b 的草地,除去一個嚴格內部的 c*d 的子草地,使得總的舒服度最大。

?

【輸入數據】

第1行:6個整數,M , ?N, ?b, ??a, ??d, ??c

第2~N+1行:每行 M 個整數,第 i行j列的整數 Fi,j 表示,第 i行j列的單位草地的舒服度。

?

【輸出數據】

一個整數,表示最大的舒服值。

?

【樣例輸入】

8 5 5 3 2 1

1 5 10 3 7 1 2 5

6 12 4 4 3 3 1 5

2 4 3 1 6 6 19 8

1 1 1 3 4 2 4 5

6 6 3 3 3 2 2 2

?

【樣例輸出】

70

?

?

【數據說明】

下面的圖片就是對樣例的解釋,陰影區域就是最佳的選擇方案。

?

比如方案 4 1 4 1 就是顯然非法的,因為篝火出現出現在了選定草地的邊界,學生們無法嚴格圍住篝火。

?

?

【數據范圍】

1 ≤ Fi,j ≤ 100

3 ≤ a ≤ N

3 ≤ b ≤ M

1 ≤ c ≤ a-2

1 ≤ d ≤ b-2

對于 40% 的數據 N,M ≤ 10

對于 60% 的數據 N,M ≤ 150

對于 100% 的數據 N,M ≤ 1000

?


?

這題其實就是求一個矩陣里的最小值。

然后就可以行做一遍,列做一遍。

?

我們可以一行一行的求出每個連續b-d-1個c*d矩形的最小值。再基于這個最小值,一列一列的求出每個a*b大矩形中和最小的c*d矩形。這樣我們就可以找到最優的舒服值了。本算法的時間復雜度是O(MN)。

原本用優先隊列。。然后超時了4個點哭。。

然后用單調隊列就巨快了。。orz。。

?

1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 9 const int N=1100; 10 int n,m,A,B,C,D; 11 int a[N][N],c[N][N],s[N][N],t[N][N],p[N][N],rr[N][N],R[N][N]; 12 struct node{int x,d;}q[N*N]; 13 14 int maxx(int x,int y){return x>y ? x:y;} 15 16 17 void solve() 18 { 19 node k; 20 int ind,l,r; 21 for(int i=1;i<=n;i++) 22 { 23 l=1;r=0; 24 for(int j=1;j+D-1<=B-2;j++) 25 { 26 k.x=j;k.d=p[i][j]; 27 while(q[r].d>k.d && l<=r) r--; 28 q[++r]=k; 29 ind=j; 30 } 31 for(int j=1;j+B-2<=m;j++) 32 { 33 while(q[l].x<j) l++; 34 rr[i][j]=q[l].d; 35 ind++;k.x=ind;k.d=p[i][ind]; 36 while(q[r].d>k.d && l<=r) r--; 37 q[++r]=k; 38 } 39 } 40 for(int i=1;i<=m;i++) 41 { 42 l=1;r=0; 43 for(int j=1;j+C-1<=A-2;j++) 44 { 45 k.x=j;k.d=rr[j][i]; 46 while(q[r].d>k.d && l<=r) r--; 47 q[++r]=k; 48 ind=j; 49 } 50 for(int j=1;j+A-2<=n;j++) 51 { 52 while(q[l].x<j) l++; 53 R[j][i]=q[l].d; 54 ind++;k.x=ind;k.d=rr[ind][i]; 55 while(q[r].d>k.d && l<=r) r--; 56 q[++r]=k; 57 } 58 } 59 int ans=0; 60 for(int i=1;i+A-1<=n;i++) 61 for(int j=1;j+B-1<=m;j++) 62 ans=maxx(ans,t[i][j]-R[i+1][j+1]); 63 printf("%d\n",ans); 64 } 65 66 int main() 67 { 68 // freopen("a.in","r",stdin); 69 freopen("trip.in","r",stdin); 70 freopen("trip.out","w",stdout); 71 scanf("%d%d%d%d%d%d",&m,&n,&B,&A,&D,&C); 72 for(int i=1;i<=n;i++) 73 for(int j=1;j<=m;j++) 74 scanf("%d",&a[i][j]); 75 memset(s,0,sizeof(s)); 76 for(int i=1;i<=n;i++) 77 for(int j=1;j<=m;j++) 78 { 79 s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]; 80 } 81 for(int i=1;i+A-1<=n;i++) 82 for(int j=1;j+B-1<=m;j++) 83 t[i][j]=s[i+A-1][j+B-1]-s[i+A-1][j-1]-s[i-1][j+B-1]+s[i-1][j-1]; 84 for(int i=1;i+C-1<=n;i++) 85 for(int j=1;j+D-1<=m;j++) 86 p[i][j]=s[i+C-1][j+D-1]-s[i+C-1][j-1]-s[i-1][j+D-1]+s[i-1][j-1]; 87 solve(); 88 return 0; 89 }

?


點分治裸題。。

先找出樹的重心,對于每個點維護一個到樹的重心的乘積d[x]。

然后找經過樹的重心的樹鏈是否有乘積為k的。

然后分治算各個子樹。

ps:學了奧爺爺的線性求逆元。。強啊。。

1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<vector> 6 #include<queue> 7 using namespace std; 8 9 typedef long long LL; 10 const int N=1000100,M=1000010,mod=1000003,INF=(int)1e9; 11 int n,len,sl,tl,a1,a2; 12 LL K,d[N],val[N],t[N],s[N],v[M],ny[M]; 13 int first[N],size[N],mark[N],id[M]; 14 struct node{ 15 int x,y,next; 16 }a[2*N]; 17 18 int minn(int x,int y){return x<y ? x:y;} 19 20 LL quickpow(LL x,LL y) 21 { 22 LL ans=1; 23 while(y) 24 { 25 if(y&1) ans=ans*x%mod; 26 x=x*x%mod; 27 y/=2; 28 } 29 return ans; 30 } 31 32 int ins(int x,int y) 33 { 34 a[++len].x=x;a[len].y=y; 35 a[len].next=first[x];first[x]=len; 36 } 37 38 void find_root(int x,int fa,int tot,int &root) 39 { 40 size[x]=1; 41 bool bk=1; 42 for(int i=first[x];i;i=a[i].next) 43 { 44 int y=a[i].y; 45 if(mark[y] || y==fa) continue; 46 find_root(y,x,tot,root); 47 size[x]+=size[y]; 48 if(2*size[y]>tot) bk=0; 49 } 50 if(bk && 2*(tot-size[x])<=tot) root=x; 51 } 52 53 void DFS(int x,int fa,int root) 54 { 55 d[x]=d[fa]*val[x]%mod; 56 t[++tl]=d[x];id[tl]=x; 57 LL now=(ny[d[x]]*K%mod)*val[root]%mod; 58 if(v[now]) 59 { 60 int X=x,Y=v[now]; 61 if(X>Y) swap(X,Y); 62 if(X<a1) a1=X,a2=Y; 63 else if(X==a1 && Y<a2) a2=Y; 64 } 65 size[x]=1; 66 for(int i=first[x];i;i=a[i].next) 67 { 68 int y=a[i].y; 69 if(mark[y] || y==fa) continue; 70 DFS(y,x,root); 71 size[x]+=size[y]; 72 } 73 } 74 75 int dfs(int x,int tot) 76 { 77 find_root(x,0,tot,x); 78 // printf("tot = %d root = %d\n",tot,x); 79 mark[x]=1; 80 sl=0;s[++sl]=val[x]; 81 d[x]=val[x]; 82 for(int i=first[x];i;i=a[i].next) 83 { 84 int y=a[i].y; 85 if(mark[y]==1) continue; 86 tl=0; 87 DFS(y,x,x); 88 for(int j=1;j<=tl;j++) 89 { 90 s[++sl]=t[j]; 91 if(v[t[j]]==0) v[t[j]]=id[j]; 92 else v[t[j]]=minn(v[t[j]],id[j]); 93 } 94 } 95 if(v[K]) 96 { 97 int X=x,Y=v[K]; 98 if(X>Y) swap(X,Y); 99 if(X<a1) a1=X,a2=Y; 100 else if(X==a1 && Y<a2) a2=Y; 101 } 102 for(int i=1;i<=sl;i++) v[s[i]]=0; 103 for(int i=first[x];i;i=a[i].next) 104 { 105 int y=a[i].y; 106 if(mark[y]==1) continue; 107 dfs(y,size[y]); 108 } 109 } 110 111 int main() 112 { 113 // freopen("a.in","r",stdin); 114 freopen("multik.in","r",stdin); 115 freopen("multik.out","w",stdout); 116 scanf("%d%d",&n,&K); 117 len=0;a1=INF;a2=INF; 118 memset(v,0,sizeof(v)); 119 memset(mark,0,sizeof(mark)); 120 memset(first,0,sizeof(first)); 121 ny[1]=1; 122 for(int i=2;i<=mod;i++) 123 ny[i]=(mod-(mod/i))*ny[mod%i]%mod; 124 // ny[i]=quickpow(i,mod-2); 125 for(int i=1;i<=n;i++) 126 scanf("%d",&val[i]); 127 for(int i=1;i<n;i++) 128 { 129 int x,y; 130 scanf("%d%d",&x,&y); 131 ins(x,y); 132 ins(y,x); 133 } 134 dfs(1,n); 135 if(a1<INF) printf("%d %d\n",a1,a2); 136 else printf("No solution\n"); 137 return 0; 138 }

?

轉載于:https://www.cnblogs.com/KonjakJuruo/p/6048138.html

總結

以上是生活随笔為你收集整理的【20161109】noip模拟赛的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。