1. 程式人生 > >Codeforces Round #352 (Div. 2) ABCD

Codeforces Round #352 (Div. 2) ABCD

Problems
#Name
A standard input/output 1 s, 256 MB Submit Add to favourites  x3197
B standard input/output 2 s, 256 MB Submit Add to favourites  x2870
C standard input/output 2 s, 256 MB Submit Add to favourites  x664
D standard input/output 1 s, 256 MB Submit Add to favourites  x248

A Summer Camp

題意:有個 "123456789101112131415..."這樣規律的字串,求其中第n個字元是什麼。 (1 ≤ n ≤ 1000) 

題解:暴力找,n只有1000,來個迴圈從1開始,整數分解,啪啪啪。

程式碼:

 1 //#pragma comment(linker, "/STACK:102400000,102400000")
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<iostream>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<cmath>
 8
#include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define MZ(array) memset(array, 0, sizeof(array)) 14 #define MF1(array) memset(array, -1, sizeof(array)) 15 #define MINF(array) memset(array, 0x3f, sizeof(array)) 16 #define REP(i,n) for(i=0;i<(n);i++) 17
#define FOR(i,x,n) for(i=(x);i<=(n);i++) 18 #define FORD(i,x,y) for(i=(x);i>=(y);i--) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("huzhi.txt","w",stdout) 25 #define MP make_pair 26 #define PB push_back 27 #define PF push_front 28 #define PPF pop_front 29 #define PPB pop_back 30 typedef long long LL; 31 typedef unsigned long long ULL; 32 33 const double PI=acos(-1.0); 34 const double EPS=1e-10; 35 36 int farm(int n){ 37 int i; 38 for(i=1; true; i++){ 39 int j=i,k=0; 40 while(j){ 41 j/=10; 42 k++; 43 } 44 if(n>k)n-=k; 45 else{ 46 if(n==k)return i%10; 47 j=i; 48 int k2=0; 49 // printf("%d!",j); 50 while(j){ 51 j/=10; 52 k2++; 53 if(k-k2==n)return j%10; 54 } 55 } 56 } 57 } 58 59 int main(){ 60 int n; 61 RD(n); 62 WN(farm(n)); 63 return 0; 64 }
View Code

B. Different is Good

題意:給出一個小寫字母字串,可以對其中某個位置修改,要求以最少的修改次數,使其所有子串不同,輸出修改次數,無解輸出-1。

題解:

說是子串不同,其實單個字母就算一個子串,必須使所有字母不同。那超過26的就直接不行,不超過26的,統計各個字母的出現次數。

統計各個字母溢位字數和sum(對有出現的字母,每個字母出現次數-1,加和),統計沒有出現的字母的個數last,last大於等於sum就輸出sum,否則輸出-1。

C. Recycling Bottles

題意:兩個人撿垃圾,給出兩個人的座標、垃圾桶座標、各個垃圾座標,人有兩種選擇,可以【不動】,也可以【選一個垃圾,跑去垃圾座標再跑去垃圾桶座標】。要撿完所有垃圾,讓兩個人的行走距離的和最小,輸出距離最小值。

題解:主要看第一次撿垃圾,因為之後都是【從垃圾桶走到垃圾,再走回垃圾桶】,所以主要看第一次【從初始座標走到垃圾】這個能節省多少距離。

這個節省的是【從垃圾桶走到這個垃圾】的時間。

定義Gain = dis(垃圾,垃圾桶) - dis(人,垃圾),Gain越大效果越好,Gain為負數就是反效果。

首先分別對兩個人找到他們Gain最高的垃圾和第二高的垃圾,因為他們可能選到同一個垃圾,所以找個第二高的備用。

所以兩個人如果有一個Gain為負數,那就只用另一個人撿就行了。兩個都為負數,就選個負得少一點的撿。

注意處理選到同一個垃圾的情況,我是分了5種方式,分別是

1.都撿最碉的

2.A撿A的最碉的,B撿B的第二碉的

3.B撿B的最碉的,A撿A的第二碉的

4.A撿最碉,B不撿

5.B撿最碉,B不撿

其中如果兩個人選的是一個,就不考慮這個方式。對比各種方式Gain的大小,選最大的,穩。

程式碼:

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<map>
  9 #include<set>
 10 #include<stack>
 11 #include<queue>
 12 using namespace std;
 13 #define MZ(array) memset(array, 0, sizeof(array))
 14 #define MF1(array) memset(array, -1, sizeof(array))
 15 #define MINF(array) memset(array, 0x3f, sizeof(array))
 16 #define REP(i,n) for(i=0;i<(n);i++)
 17 #define FOR(i,x,n) for(i=(x);i<=(n);i++)
 18 #define FORD(i,x,y) for(i=(x);i>=(y);i--)
 19 #define RD(x) scanf("%d",&x)
 20 #define RD2(x,y) scanf("%d%d",&x,&y)
 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
 22 #define WN(x) printf("%d\n",x);
 23 #define RE  freopen("D.in","r",stdin)
 24 #define WE  freopen("huzhi.txt","w",stdout)
 25 #define MP make_pair
 26 #define PB push_back
 27 #define PF push_front
 28 #define PPF pop_front
 29 #define PPB pop_back
 30 typedef long long LL;
 31 typedef unsigned long long ULL;
 32 
 33 const double PI=acos(-1.0);
 34 const double EPS=1e-10;
 35 const double MA=1e10*100;
 36 
 37 const int MAXN=111111;
 38 int n;
 39 int ax,ay,bx,by,cx,cy;
 40 int X[MAXN],Y[MAXN];
 41 
 42 double dis(int x,int y,int x2,int y2) {
 43     LL xx=x-x2;
 44     LL yy=y-y2;
 45     return sqrt(xx*xx+yy*yy);
 46 }
 47 
 48 double judge(int x,int y,int no) {
 49     if(no==-1)return MA;
 50     return dis(X[no],Y[no],cx,cy) - dis(x,y,X[no],Y[no]);
 51 }
 52 
 53 int findNearest(int x,int y,int &no2) {
 54     int no;
 55     double nd, nd2;
 56     no=0;
 57     no2=-1;
 58     nd=judge(x,y,no);
 59     nd2=MA;
 60     for(int i=1; i<n; i++) {
 61         double d=judge(x,y,i);
 62         if(d>nd) {
 63             no2=no;
 64             nd2=nd;
 65             no=i;
 66             nd=d;
 67         } else if(no2==-1 || d>nd2) {
 68             no2=i;
 69             nd2=d;
 70         }
 71     }
 72     return no;
 73 }
 74 
 75 bool ganked[MAXN];
 76 
 77 double farm() {
 78     MZ(ganked);
 79     int p[2],pp[2];
 80     double d[2],dd[2];
 81     p[0]=findNearest(ax,ay,pp[0]);
 82     p[1]=findNearest(bx,by,pp[1]);
 83     int no1[5]={p[0],   p[0],   pp[0],  p[0],   -1};
 84     int no2[5]={p[1],   pp[1],  p[1],   -1,     p[1]};
 85     int choose=-1;
 86     double gain;
 87     int i;
 88     REP(i,5){
 89         if(no1[i]==no2[i])continue;
 90         double g = 0.0;
 91         if(no1[i]!=-1) g+=judge(ax,ay,no1[i]);
 92         if(no2[i]!=-1) g+=judge(bx,by,no2[i]);
 93         if(choose==-1 || g>gain){
 94             choose = i;
 95             gain = g;
 96         }
 97     }
 98     bool bad[2]= {0};
 99     int q[2] = {no1[choose],no2[choose]};
100     if(no1[choose]==-1)bad[0]=1;
101     if(no2[choose]==-1)bad[1]=1;
102 //    cout<<q[0]<<','<<q[1]<<endl;
103     double re=0.0;
104     int onex[2]={ax,bx};
105     int oney[2]={ay,by};
106     REP(i,2) if(!bad[i]) {
107         re += dis(onex[i],oney[i],X[q[i]],Y[q[i]]);
108         ganked[q[i]]=1;
109     }
110 //    cout<<re<<endl;
111     REP(i,n) {
112         if(!ganked[i])re += dis(cx,cy,X[i],Y[i])*2;
113         else re+= dis(cx,cy,X[i],Y[i]);
114     }
115     return re;
116 }
117 
118 int main() {
119     int i;
120     scanf("%d%d%d%d%d%d",&ax,&ay,&bx,&by,&cx,&cy);
121     RD(n);
122     REP(i,n)RD2(X[i],Y[i]);
123     printf("%.10f\n",farm());
124     return 0;
125 }
View Code
D standard input/output 1 s, 256 MB Submit Add to favourites  x252

D. Robin Hood

題意:羅賓漢劫富濟貧,每天偷最有錢的人一塊錢,給最窮的人。有多種選擇的話隨機偷。給出各個人初始錢數,羅賓漢偷錢天數,輸出最後最有錢的人和最窮的人的錢數差。

人數n,天數k (1 ≤ n ≤ 500 000, 0 ≤ k ≤ 10^9)

題解:

偷10的9次方天,暴力一天一天偷肯定不行,要想辦法一下計算很多天的偷。

我們可以用map來找最窮最有錢的人。map<int,int>,第一個int代表錢數,第二個int代表這個錢數的人數。就叫這個map叫S好了。

每次找到最有錢的人的錢數r,最沒錢的人錢數l,一次我們可以幫x個人每個人偷e塊錢,操作如下:

1 S[l]-=x;
2 S[r]-=x;
3 如果S[l]或者S[r]為0,就把它從S裡刪掉。
4 S[l+e]+=x;
5 S[r-e]+=x;

這個簡單,關鍵是確定每次的人數x和錢數e。

1.不能偷多,我們不能讓最有錢的人們被偷得比第二有錢的人們窮,也不能讓最窮的人們比第二窮的人們有錢。所以

e <= min (最有錢的人們的錢數 - 第二有錢人們的錢數  ,  第二窮的人們的錢數 - 最窮的人們的錢數)

2.確定人數x,設最窮的人的人數ln,最有錢的人的人數rn,則

x <= min(ln, rn)

3.還要看羅賓漢剩餘的天數k,量力而行

e <= k/x

(把x個人每人偷e塊錢,需要e*x天,天數要k>=e*x)

如果因為此限制,e必須為0,則說明羅賓漢無力縮小貧富差距了,直接輸出當前的貧富差距。

4.如果ln和rn不同,偷完後會剩下abs(rn-ln)人,如果這時k不夠了,無法把剩下的人改變e,豈不是貧富差距拉大,所以要 

1         maxX = max(ln, rn)
2         if(x != maxX){
3             e=min(k/maxX, e);
4             e=max(1,e);
5         }

也就是限制e,使得k足夠,貧富差距不會拉大。

5.預先可以快速判斷是否能將貧富差距縮到最小,也就是算一下錢平均值,然後對每個大於平均值的減去平均值,加和得到sum,也就是拉到平均值所需要的天數,如果羅賓漢天數k大於這個天數,則直接輸出(sum%n==0 ? 0 : 1)

(不能整除的話說明最後貧富差距不會縮小到0,最小是1)

大概就是上面這些條件吧,就可以快速地每次把x個人每人偷e塊錢,最後他們會越來越多聚集到同一錢數,時間複雜度我也不會算,好像不是很大。

程式碼:

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<map>
  9 #include<set>
 10 #include<stack>
 11 #include<queue>
 12 using namespace std;
 13 #define MZ(array) memset(array, 0, sizeof(array))
 14 #define MF1(array) memset(array, -1, sizeof(array))
 15 #define MINF(array) memset(array, 0x3f, sizeof(array))
 16 #define REP(i,n) for(i=0;i<(n);i++)
 17 #define FOR(i,x,n) for(i=(x);i<=(n);i++)
 18 #define FORD(i,x,y) for(i=(x);i>=(y);i--)
 19 #define RD(x) scanf("%d",&x)
 20 #define RD2(x,y) scanf("%d%d",&x,&y)
 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
 22 #define WN(x) printf("%d\n",x);
 23 #define RE  freopen("D.in","r",stdin)
 24 #define WE  freopen("huzhi.txt","w",stdout)
 25 #define MP make_pair
 26 #define PB push_back
 27 #define PF push_front
 28 #define PPF pop_front
 29 #define PPB pop_back
 30 typedef long long LL;
 31 typedef unsigned long long ULL;
 32 
 33 const double PI=acos(-1.0);
 34 const double EPS=1e-10;
 35 
 36 const int MAXN=511111;
 37 int n,k;
 38 int a[MAXN];
 39 
 40 int farm() {
 41     int i;
 42     LL sum=0;
 43     REP(i,n)sum+=a[i];
 44     double avg = 1.0*sum/n;
 45     int need=0;
 46     REP(i,n) {
 47         if(a[i]>avg)need+=ceil(a[i]-avg);
 48         if(need>k)break;
 49     }
 50     if(need<=k)return sum%n==0?0:1;
 51     if(n==1)return 0;
 52     map<int,int> s;
 53     REP(i,n)s[a[i]]++;
 54     map<int,int>::iterator q,w,q2,w2;
 55     while(k) {
 56         q = s.begin();
 57         w = s.end();
 58         w--;
 59         int l =  q->first;
 60         int r = w->first;
 61         if(l==r)break;
 62         q2=q;
 63         w2=w;
 64         q2++;
 65         w2--;
 66         int e,man;
 67         e = min(q2->first - l, r - w2->first);
 68         man = min(q->second, w->second);
 69         e = min(k/man,e);
 70 //        printf("%d,%d,%d\n",e,k,man);
 71         if(e==0)break;
 72         int maxMan = max(q->second, w->second);
 73         if(man != maxMan){
 74             e=min(k/maxMan, e);
 75             e=max(1,e);
 76         }
 77         q->second-=man;
 78         w->second-=man;
 79         if(q->second==0)s.erase(q);
 80         if(w->second==0)s.erase(w);
 81         k-=e*man;
 82         r-=e;
 83         l+=e;
 84         s[r]+=man;
 85         s[l]+=man;
 86 
 87     }
 88     q = s.begin();
 89     w = s.end();
 90     w--;
 91     int l =  q->first;
 92     int r = w->first;
 93     return r-l;
 94 }
 95 
 96 int main() {
 97     int i;
 98     RD2(n,k);
 99     REP(i,n)RD(a[i]);
100     WN(farm());
101     return 0;
102 }
View Code