題號 | A | B | C | D | E | F | G | H | I | J |
狀態 | Ο | . | . | . | Ø | Ο | . | . | . | Ο |
題意:給出兩個序列$rmq$相等的定義:任意子區間最小值相等,然后給出$a、b$兩個數組,求最長的前綴相等序列長度。
題解:我們考慮前$k$個數字已經是相等序列了,這個時候我們加入第$k+1$個元素$x$,如果$x$比第$k$個元素大,會發現這絕對不會使序列變的不合法。當$x$比第$k$個小時,我們發現$x$會影響從$k$往前開始,從后往前直到出現第一個比$x$小的數字。在這個位置會改變最小值的關系,所以我們用一個權值單調遞增的單調棧來維護序列,如果每個地方影響的位置都相同,則合法,否則就break。

#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; int n; const int maxn=100010; int a[maxn],b[maxn]; struct node{ int val,pos; }sta1[maxn],sta2[maxn]; int top1,top2; int main(){ while(cin>>n){ top1=top2=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } int ans=0; int flag=1; for(int i=1;i<=n;i++){ scanf("%d",&b[i]); while(top1!=0&&a[i]<sta1[top1].val){ top1--; } sta1[++top1].val=a[i]; sta1[top1].pos=i; int x=i-sta1[top1-1].pos; while(top2!=0&&b[i]<sta2[top2].val){ top2--; } sta2[++top2].val=b[i]; sta2[top2].pos=i; int y=i-sta2[top2-1].pos; if(x==y&&flag){ ans++; }else{ flag=0; } } printf("%d\n",ans); } }
E.ABBA
題意:構造一個長度為2*(n+m)的AB串,使這個串可以划分成n和“AB”的子序列和m個“BA”的子序列,求方案數量
題解:我們將符合條件的串稱為合法序列,比如“AAABBBB”不可能是合法序列,“AAAABBB”就可能是一個合法序列。設$dp[i][j]$表示用了$i$個$A$和$j$個$B$組成的合法序列的方案數,這里的$i$也就是A的個數最多是$j+n$個,即j個“BA”的“A”和n個“AB”的‘A’,(j個B全部用來組成BA,這是最多的情況),此時我們可以轉移到$dp[i+1][j]$,同理,B也是一樣的轉移方式。

#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=2010; int n,m; ll p=1e9+7; ll dp[maxn][maxn]; int main(){ while(cin>>n>>m){ for(int i=0;i<=n+m;i++){ for(int j=0;j<=n+m;j++)dp[i][j]=0; } dp[0][0]=1; for(int i=0;i<=n+m;i++){ for(int j=0;j<=n+m;j++){ if(i+1<=j+n){ dp[i+1][j]=(dp[i+1][j]+dp[i][j])%p; } if(j+1<=i+m){ dp[i][j+1]=(dp[i][j+1]+dp[i][j])%p; } } } printf("%lld\n",dp[n+m][n+m]); } }
題意:給出坐標系上的三個點,然后在三角形內隨機生成一個點,和三個點相連,問面積最大的三角形的期望是多少。
思路:由於題目說輸出ans*36,並且保證這是整數,說明答案如果是個分數,分母肯定是36的因子,就大膽的隨機生成了一些點,算了一下期望,發現就是三角形面積的11/2。
要注意隨機數的生成是有范圍的,最多生成2^16這么大的數。longlong取模也要用labs

#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; int main(void) { ll a1, b1, a2, b2, a3, b3; while (~scanf("%lld %lld %lld %lld %lld %lld", &a1, &b1, &a2, &b2, &a3, &b3)) { long long x1=a2-a1,x2=a3-a1,y1=b2-b1,y2=b3-b1; long long s=11*labs(x1*y2-x2*y1); printf("%lld\n", s); } return 0; }
J.
題意:給出x,a,y,b,判斷x/a與y/b的大小,0<=x,y<=1e18,1<=a,b<=1e9。
思路:x/a=x//a+x%a,y/b也一樣拆開來,先判斷x//a和y//b的大小,如一樣,再判斷(x%a)*b和(y%b)*a的大小。

#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; using namespace std; int main(void) { long long x, y, a, b; while (~scanf("%lld %lld %lld %lld", &x, &a, &y, &b)) { if (x / a > y / b) { printf(">\n"); } else if (x / a < y / b) { printf("<\n"); } else { x %= a; y %= b; if (x * b > y * a) { printf(">\n"); } else if (x * b < y * a) { printf("<\n"); } else { printf("=\n"); } } } return 0; }