标签:
# | Name | ||
---|---|---|---|
A |
standard input/output
1 s, 256 MB |
x3197 | |
B |
standard input/output
2 s, 256 MB |
x2870 | |
C |
standard input/output
2 s, 256 MB |
x664 | |
D |
standard input/output
1 s, 256 MB |
x248 | |
E |
standard input/output
2 s, 256 MB |
x2 |
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 }
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 }
D |
standard input/output
1 s, 256 MB |
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 }
Codeforces Round #352 (Div. 2) ABCD
标签:
原文地址:http://www.cnblogs.com/yuiffy/p/5485377.html