校内集训(20170903)
T1:卡片(card)
【題目描述】
lrb喜歡玩卡牌。他手上現在有張牌,每張牌的顏色為紅綠藍中的一種。現在他有兩種操作。一是可以將兩張任意位置的不同色的牌換成一張第三種顏色的牌;二是可以將任意位置的兩張相同顏色的牌換成一張該顏色的牌。兩個操作后都可以將生成的牌放到任意位置。現在他想知道,最后一張牌可能是什么顏色的。
【輸入描述】
第一行輸入一個,表示卡牌數量。
第二行輸入一個由’B’,’G’,’R’組成的長度為的字符串,分別表示卡牌的顏色為藍色、綠色、紅色中的一種。
【輸出描述】
輸出’B’,’G’,’R’中的若干個字母,按字典序輸出。代表可能的最后一張牌的顏色。
【樣例】
| 輸入1 | 輸出1 |
| 2 RB | G |
| 輸入2 | 輸出2 |
| 3 GRG | BR |
| 輸入3 | 輸出3 |
| 4 BBBB | B |
【數據范圍】
對于100%的數據,n<=200
——————————————————我是分割線————————————————————
這是一道簡單分析題。(入門難度。。不要吐槽)
很顯然我們發現如果3張牌都超過一張,三種情況都會出現(BGR)
那么如果有2張牌都超過2張,同上
剩下3種情況:
1,1,0(數字表示牌的數量)那么答案就是牌數是0的那張
2,1,0(2表示2張以上)那么答案就是牌數為1和0的兩張
1,0,0(1表示一張以上)那么答案就是牌數為1的那一張
然后。。。做完了
下面貼上代碼
#include<cstdio> using namespace std; int a[4],n; int er,yi,sa; char ch; char ans[3]={'B','G','R'}; void swap(int &a,int &b){a^=b;b^=a;a^=b;} int main(){freopen("card.in","r",stdin);freopen("card.out","w",stdout);scanf("%d",&n);for(int i=1;i<=n;i++){ch=getchar();while(ch<'A'||ch>'Z')ch=getchar();if(ch=='B')a[1]++;else if(ch=='G')a[2]++;else if(ch=='R')a[3]++;}for(int i=1;i<=3;i++)if(a[i]>=2)er++;for(int i=1;i<=3;i++)if(a[i]>=1)yi++; if(er>=2||yi==3)puts("BGR");else if(er==1&&yi==2){int x,y;for(int i=1;i<=3;i++)if(a[i]==0)x=i;else if(a[i]==1)y=i;if(x>y)swap(x,y);printf("%c%c\n",ans[x-1],ans[y-1]);}else if(yi==2){int x;for(int i=1;i<=3;i++)if(!a[i])x=i;printf("%c\n",ans[x-1]);}else if(yi==1){int x;for(int i=1;i<=3;i++)if(a[i])x=i;printf("%c\n",ans[x-1]);}fclose(stdin);fclose(stdout); }————————————————我是分割線——————————————————
T2:取數(win)
【題目描述】
lrb目前有個數字,他想知道這個數中選出若干個數,平均數減中位數的最大值是多少。可以證明,對于一個遞增數列,如果是平均數減中位數最大時的中位數,表示在兩邊分別取相鄰數字的數量,表示以為中位數,在兩側各取相鄰個數時平均數減中位數的值,那么為關于的單峰函數。
【輸入描述】
第一行為,為數字個數。
第二行有個數,分別代表個數字。
【輸出描述】
輸出一個數,為平均數減中位數的最大值,保留兩位小數。
【樣例】
| 輸入 | 輸出 |
| 4 1 2 3 4 | 0.33 |
【數據范圍】
對于60%的數據,n<=21
對于75%的數據,n<=1000
對于100%的數據,n<=10^5,0<=ai<=10^6
——————————————————我是分割線————————————————————
這題首先我們要想到的就是枚舉中位數。
那么假設我們已知某一個數是中位數,那么我們怎么求最優的答案呢?
對于一個已經排序過的數列,
顯然我們要在這個中位數的左邊和右邊同時取相同數量的數。
對于中位數的左邊,顯然越靠近中位數的數越優,
對于中位數的右邊,越遠離中位數的數越優。
所以對于第i個數作為中位數的情況,我們左邊從第i-1位開始向左取數,右邊從第n位開始向左取數。而取數的個數自然就是三分啦!(三分的過程用前綴和O(1)求平均數)
至于為什么偶數個數的數列不是最優解,這個我留個坑以后來填。
下面貼代碼(當然我寫了偶數版本)
#include<cstdio> #include<algorithm> #define MN 100005 using namespace std; int a[MN],n; long long sum[MN]; double ans=-100000000; int main(){freopen("win.in","r",stdin);freopen("win.out","w",stdout);scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);sort(a+1,a+n+1);int l=0,r=0,lm=0,rm=0,le=0;double la=a[1],ra=a[1];for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];for(int i=1;i<=n;i++){le=min(i-1,n-i);le=max(le,0);l=0,r=le;while(l<r-1){lm=l+(r-l)/3,rm=r-(r-l)/3;la=(double)(sum[i-1]-sum[i-1-lm]+sum[n]-sum[n-lm]+a[i])/(double)(2*lm+1);ra=(double)(sum[i-1]-sum[i-1-rm]+sum[n]-sum[n-rm]+a[i])/(double)(2*rm+1);if(la<ra)l=lm+1;else r=rm-1;}la=(double)(sum[i-1]-sum[i-1-l]+sum[n]-sum[n-l]+a[i])/(double)(2*l+1);ra=(double)(sum[i-1]-sum[i-1-r]+sum[n]-sum[n-r]+a[i])/(double)(2*r+1);if(la<ra)ans=max(ans,ra-(double)a[i]);else ans=max(ans,la-(double)a[i]);}la=ra=(double)(a[1]+a[2])/2.0;for(int i=1;i<n;i++){le=min(i-1,n-i-1);le=max(le,0);l=0,r=le;while(l<r-1){lm=l+(r-l)/3,rm=r-(r-l)/3;la=(double)(sum[i-1]-sum[i-1-lm]+sum[n]-sum[n-lm]+a[i]+a[i+1])/(double)(2*lm+2);ra=(double)(sum[i-1]-sum[i-1-rm]+sum[n]-sum[n-rm]+a[i]+a[i+1])/(double)(2*rm+2);if(la<ra)l=lm+1;else r=rm-1;}la=(double)(sum[i-1]-sum[i-1-l]+sum[n]-sum[n-l]+a[i]+a[i+1])/(double)(2*l+2);ra=(double)(sum[i-1]-sum[i-1-r]+sum[n]-sum[n-r]+a[i]+a[i+1])/(double)(2*r+2);if(la<ra)ans=max(ans,ra-(double)((double)(a[i]+a[i+1])/(double)2));else ans=max(ans,la-(double)((double)(a[i]+a[i+1])/(double)2));}printf("%.2lf\n",ans);fclose(stdin);fclose(stdout); }?————————————————我是分割線————————————————
T3:密碼(key)
【題目描述】
lrb去柜員機取錢,并輸入了他的四位密碼。但是這一切都被一個黑幫拍攝了下來。幸好,這一次他的銀行卡里并沒有剩余任何錢。lrb知道了他的賬戶被異常登錄后十分害怕,然后修改了他的密碼。從此以后他為了不被看出密碼,他開始“徐晃”。但這一切還是被拍攝了下來,拍攝多次以后,這個黑幫找到了你,希望你在一秒內幫他算出lrb的可能使用的密碼數量。
【輸入描述】
第一行輸入一個,為lrb被拍攝的動作次數。
接下來行,每行第一個數為,表示lrb接下來的手指移動次數,接下來為一個長度為的數字串,表示lrb手指經過的軌跡。lrb手指經過的位置,可能沒有按,也有可能按了多次。
【輸出描述】
輸出一行,為可能的密碼數量。
【樣例】
| 輸入 | 輸出 |
| 2 3 123 3 234 | 5 |
| 解釋 | |
| lrb可能用的是2222,2223,2233,2333,3333五種密碼 | |
【數據范圍】
設所有軌跡串的總長度為。
對于35%的數據,L<5000
對于100%的數據,1<=n<=1000,1<=t<=10^4,L<=10^6
——————————————————我是分割線——————————————————
這道題有一個簡單思路(想不到的都是腦子抽了,比如我)
我們只要枚舉所有的密碼就好了
然后就是如何在O(n)時間內check一個密碼
我們只要開一個數組記錄從每一位開始,后面的第一個0-9分別在第幾位,如果都能夠找到,那么密碼合法。
下面貼代碼
#include<cstdio> #define MN 1005 #define M 1000005 #define F(x,l,r) for(int x=l;x<=r;x++) using namespace std; char e[M];int f[M][10],ans,n,t[MN]; int main(){freopen("key.in","r",stdin);freopen("key.out","w",stdout);scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%s",&t[i],e+t[i-1]),t[i]+=t[i-1];for(int i=0;i<=9;i++)f[t[n]][i]=t[n];for(int i=t[n]-1;i>=0;i--){for(int j=0;j<=9;j++)f[i][j]=f[i+1][j];f[i][e[i]-'0']=i;}F(a,0,9)F(b,0,9)F(c,0,9)F(d,0,9){int tot=0;F(i,0,n-1)if(f[f[f[f[t[i]][a]][b]][c]][d]<t[i+1])tot++;ans+=tot==n;}printf("%d\n",ans); }?
轉載于:https://www.cnblogs.com/ghostfly233/p/7473367.html
總結
以上是生活随笔為你收集整理的校内集训(20170903)的全部內容,希望文章能夠幫你解決所遇到的問題。