2013多校第七场

hdu 4666

题意:n个事件,op == 0 插入一个点,op == 1删除一个点,每个事件之后询问当前点里曼哈顿距离最大的值;

分析:曼哈顿距离等于abs(a.x - b.x) + abs(a.y - b.y);

就是c1*(a.x- b.x) + c2*(a.y - b.y),c1,c2取1或-1;显然只有当c1,c2去恰当值后值才是他们的曼哈顿距离,并且是最大的;

这样我们就有思路了,开1<<k个multiset,对于每个点都放入不同的multiset里,而在同一个muliset里,直接相减就是最大值;

其实就是高中的去绝对值的问题; 唉...

it1 = st.lower_bound(key); 注意st.erase(it1) 和st.erase(*it1)的区别;

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<cstring>
 7 #include<cstdlib>
 8 #include<cstdio>
 9 #include<set>
10 #include<map>
11 using namespace std;
12 const int N = 1<<5;
13 int n,k;
14 struct node{
15     int a[5];
16     int s;
17     void init(){
18         memset(a,0,sizeof(a));
19     }
20     void sum(){
21         s = 0;
22         for (int i = 0; i < 5; i++) s += a[i];
23     }
24     bool operator < (const node &p) const{
25         return s < p.s;
26     }
27 }nd[60000+10];
28 
29 multiset<node> st[N];
30 multiset<node> :: iterator it1,it2;
31 void print(){
32     int ans = 0;
33     for (int i = 0; i <(1<<k); i++) {
34         it1 = st[i].begin();
35         if (it1 == st[i].end()) continue;
36         it2 = st[i].end();
37         it2 --;
38         if (it2->s - it1->s > ans) ans = it2->s - it1->s;
39     }
40     printf("%d\n",ans);
41 
42 }
43 int main(){
44 
45     while (~scanf("%d%d",&n,&k)) {
46         for (int i = 0; i < (1<<k) ; i++) st[i].clear();
47         node t1,t2;
48         for (int w = 0; w < n; w++) {
49             int op; scanf("%d",&op);
50             if (op == 0) {
51                 t1.init();
52                 for (int i = 0; i < k; i++) {
53                     scanf("%d",&t1.a[i]);
54                 }
55                 nd[w+1] = t1;
56                 t2.init();
57                 for (int i = 0; i < (1<<k); i++) {
58                     for (int j = 0; j < k; j++) {
59                         if (i & (1<<j)) {
60                             t2.a[j] = -t1.a[j];
61                         }else t2.a[j] = t1.a[j];
62                     }
63                     t2.sum();
64                     st[i].insert(t2);
65                 }
66                 print();
67             }else {
68                 int d; scanf("%d",&d);
69                 t2.init();
70                 for (int i = 0; i < (1<<k); i++) {
71 
72                     for (int j = 0; j < k; j++) {
73                         if (i & (1<<j)) {
74                             t2.a[j] = -nd[d].a[j];
75                         }else t2.a[j] = nd[d].a[j];
76                     }
77                     t2.sum();
78                     it1 = st[i].lower_bound(t2);
79                     st[i].erase(it1);
80                 }
81                 print();
82             }
83         }
84     }
85 
86     return 0;
87 }
View Code

 

hdu 4667

题意:给你n个圆和m个三角形,求最短的绳子把他们包围起来。

分析:取出所有点与所有圆的切线的切点和两两圆的公切线的切点,和三角形的点一起求凸包;

然后相邻的点判断是否在同一个圆上,如果是就要求弧长,不然就是两点之间距离;

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<vector>
  8 #include<map>
  9 #define pbk push_back
 10 using namespace std;
 11 
 12 const double eps = 1e-8;
 13 const double PI = acos(-1.0);
 14 const int maxP = 40000+10;
 15 inline int dcmp(double x){
 16     return x<-eps ? -1 : x>eps;
 17 }
 18 inline double sqr(double x){
 19     return x*x;
 20 }
 21 struct Point {
 22     double x,y;
 23     Point(){}
 24     Point (double a,double b):x(a),y(b){}
 25     bool operator == (const Point &p)const{
 26         return (dcmp(x-p.x) == 0 && dcmp(y-p.y) == 0);
 27     }
 28     bool operator < (const Point &p)const{
 29         return dcmp(x-p.x) < 0 || (dcmp(x-p.x) == 0 && dcmp(y-p.y) < 0);
 30     }
 31     double operator * (const Point &p)const{
 32         return x*p.y - y*p.x;
 33     }
 34     double operator / (const Point &p)const{
 35         return x*p.x + y*p.y;
 36     }
 37 
 38     Point operator - (const Point &p)const{
 39         return Point(x-p.x,y-p.y);
 40     }
 41     Point operator + (const Point &p)const{
 42         return Point(x+p.x, y+p.y);
 43     }
 44     Point operator * (const double &k)const{
 45         return Point(x*k, y*k);
 46     }
 47     Point operator / (const double &k)const{
 48         return Point(x/k, y/k);
 49     }
 50 
 51     double len2(){
 52         return x*x + y*y;
 53     }
 54     double len(){
 55         return sqrt(x*x + y*y);
 56     }
 57     Point scale(const double &k){//变成长度为k的"向量"
 58         return dcmp( len() ) ? (*this) * (k / len()) : (*this);
 59     }
 60     Point turnLeft(){
 61         return Point(-y,x);
 62     }
 63     Point turnRight(){
 64         return Point(y,-x);
 65     }
 66     void input(){
 67         scanf("%lf%lf",&x,&y);
 68     }
 69     void ot(){
 70         printf("%lf %lf\n",x,y);
 71     }
 72     double Distance(const Point &p){
 73         return sqrt( sqr(x-p.x) + sqr(y-p.y) );
 74     }
 75 };
 76 
 77 struct Polygon{
 78     int n;
 79     Point p[maxP];
 80     void input(){
 81         for (int i = 0; i < n; i++){
 82             p[i].input();
 83         }
 84     }
 85     void push(const Point &pp){
 86         p[n++] = pp;
 87     }
 88 
 89     void getConvex(Polygon &c){
 90         sort(p, p+n);
 91         c.n = n;
 92         if (n == 0) return;
 93         c.p[0] = p[0]; if (n == 1) return;
 94         c.p[1] = p[1]; if (n == 2) return;
 95         int &top = c.n;
 96         top =1;
 97         for (int i = 2; i < n; i++){
 98             while (top > 0 && dcmp( (c.p[top] - p[i])*(c.p[top-1] - p[i]) ) >= 0)
 99                 top --;
100             c.p[++top] = p[i];
101         }
102         int tmp = top;
103         c.p[++top] = p[n-2];
104         for (int i = n-3; i >= 0; i--){
105             while (top > tmp && dcmp( (c.p[top] - p[i])*(c.p[top-1] - p[i]) ) >= 0)
106                 top --;
107             c.p[++top] = p[i];
108         }
109     }
110 
111 };
112 struct Circle{
113     Point c;
114     double r;
115     Circle(){}
116     Circle(const Point &a,const double &d):c(a),r(d){}
117     bool operator == (const Circle &C)const{
118         if (c == C.c && dcmp(r - C.r) == 0) return 1;
119         return 0;
120     }
121     Point getPoint(double a) {
122         return Point(c.x + cos(a) * r, c.y + sin(a) * r);
123     }
124     int CrossCircle(const Circle &C) {//0包含,1相交,2相离
125         double d = c.Distance(C.c);
126         if ( dcmp( r + C.r - d ) < 0 ) return 2;
127         if ( dcmp( d - fabs(r - C.r) ) < 0 ) return 0;
128         return 1;
129     }
130     void CrossCirclePoint(const Circle &C, Point &p1, Point &p2) {
131         double d = c.Distance(C.c);
132         double d1 = ( sqr(d) + sqr(r) - sqr(C.r) ) / (2 * d);
133         double h = sqrt(sqr(r) - sqr(d1));
134         Point p = c + ( C.c - c ).scale(d1);
135         Point vec = ( C.c - c ).turnLeft().scale(h);
136         p1 = p - vec, p2 = p + vec;
137     }
138   
139     void TangencyPoint(Point p,Point &p1,Point &p2) {//过圆外一点p的切线的切点p1,p2;
140         Point q = c + ( p -c ).scale(r);
141         double d = p.Distance(c);
142         double d1 = sqrt(sqr(d) - sqr(r));
143         Point vec = q - c;
144         double Cos = r / d, Sin = d1 / d;
145         p1 = c + Point(vec.x * Cos - vec.y * Sin, vec.y * Cos + vec.x * Sin);
146         p2 = c + Point(vec.x * Cos + vec.y * Sin, vec.y * Cos - vec.x * Sin);
147     }
148 
149  
150     double arc(const Point &a, const Point &b) {//a到b的有向弧长
151         double cp = ( a - c) * ( b - c );
152         double ret = atan2(fabs(cp), ( a - c ) / ( b - c ));
153         return cp > -eps ? ret*r : (2*PI - ret)*r;
154     }
155   
156 };
157 int n,m;
158 vector<Circle> ci;
159 vector<Point> pi;
160 Polygon H1,H2;
161 Point a[11],b[11];
162 
163 
164 //返回切线条数,a[i],b[i]分别表示第i条切线在A,B上的切点
165 int getTangents(Circle A, Circle B,Point a[],Point b[]) {
166     int cnt = 0;
167     if (dcmp( A.r - B.r ) < 0) {
168         swap(A,B); swap(a,b);
169     }
170     double d = (A.c - B.c).len2();
171     double rdiff = A.r - B.r;
172     double rsum = A.r + B.r;
173     if (d < sqr(rdiff)) return 0; //内含;
174     if (dcmp(d) == 0 && dcmp(A.r - B.r) == 0) return -1;//两圆相同
175 
176     double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);
177 
178     if (dcmp(d - sqr(rdiff)) == 0) { //内切,1条切线
179         a[cnt] = A.getPoint(base); b[cnt++] = B.getPoint(base);
180         return 1;
181     }
182     //有外公切线;
183     double ang = acos( (A.r - B.r) / sqrt(d) );
184 
185     a[cnt] = A.getPoint(base+ang); b[cnt++] = B.getPoint(base+ang);
186     a[cnt] = A.getPoint(base-ang); b[cnt++] = B.getPoint(base-ang);
187     if (dcmp(d - sqr(rsum)) == 0) { //一条内公切线
188         a[cnt] = A.getPoint(base);
189         b[cnt++] = B.getPoint(PI+base);
190     }else if (dcmp(d - sqr(rsum)) > 0) { //两条内公切线
191         double ang = acos( (A.r + B.r) / sqrt(d) );
192         a[cnt] = A.getPoint(base+ang); b[cnt++] = B.getPoint(PI+base+ang);
193         a[cnt] = A.getPoint(base-ang); b[cnt++] = B.getPoint(PI+base-ang);
194     }
195     return cnt;
196 }
197 
198 void init() {
199     H1.n = 0;
200     for (int i = 0; i < pi.size(); i++) {
201         H1.push(pi[i]);
202         for (int j = 0; j < ci.size(); j++) {
203             if ( dcmp( pi[i].Distance(ci[j].c) - ci[j].r ) == 0 ) continue;
204             Point t1,t2;
205             ci[j].TangencyPoint(pi[i],t1,t2);
206             H1.push(t1); H1.push(t2);
207         }
208     }
209     for (int i = 0; i < ci.size(); i++) {
210         double x = ci[i].c.x, y = ci[i].c.y, r = ci[i].r;
211         H1.push(Point(x-r,y));
212         H1.push(Point(x+r,y));
213         H1.push(Point(x,y-r));
214         H1.push(Point(x,y+r));//输入只有一个圆的情况
215         for (int  j = i+1; j < ci.size(); j++) {
216             int cnt = getTangents(ci[i],ci[j],a,b);
217             for (int k = 0; k < cnt; k++) {
218                 H1.push(a[k]); H1.push(b[k]);
219             }
220         }
221     }
222 }
223 int InCircle(Point a,Point b,double &len) {
224     for (int i = 0; i < ci.size(); i++ ) {
225         double d1 = a.Distance(ci[i].c);
226         double d2 = b.Distance(ci[i].c);
227         if (dcmp(d1 - ci[i].r) == 0 && dcmp(d2 - ci[i].r) == 0) {
228             len = ci[i].arc(a,b);
229            // if (dcmp(len) < 0) len = 2 * PI * ci[i].r + len;
230             return 1;
231         }
232     }
233     return 0;
234 }
235 void solve(){
236     init();
237     H1.getConvex(H2);
238     double ret = 0;
239     H2.p[H2.n] = H2.p[0];
240     for (int i = 0 ; i < H2.n; i++) {
241         double len = 0;
242         if (InCircle(H2.p[i],H2.p[i+1],len)) {
243             ret += len;
244         }else ret += H2.p[i].Distance(H2.p[i+1]);
245     }
246     printf("%.10lf\n",ret);
247 }
248 int main(){
249     while (~scanf("%d%d",&n,&m)){
250         ci.clear(); pi.clear();
251         for (int i = 0; i < n; i++) {
252             Point t; double r;
253             t.input(); scanf("%lf",&r);
254             ci.push_back(Circle(t,r));
255         }
256         for (int i = 0; i < m; i++) {
257             for (int j = 0; j < 3; j++) {
258                 Point t; t.input();
259                 pi.push_back(t);
260             }
261         }
262         solve();
263     }
264     return 0;
265 }
View Code

 

hdu 4675

题意:求和序列a只有k个不同的序列b,且gcd(b1,b2,...bn) = d的个数;

分析: 先求出公约数是b的序列的个数ans2[b],那么对于gcd() = i;的个数就是

ans[i] = ans2[i] - ans[i*j]  (j>1);从m往1推;

当时只想到一个n^3的DP,唉...

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<vector>
 8 #include<set>
 9 using namespace std;
10 typedef long long LL;
11 const int N = 300000+10;
12 const int Mod = 1000000007;
13 int a[N];
14 int n,m,k;
15 int num[N];
16 LL c[N];
17 void ex_gcd(LL a, LL b, LL &g, LL &x, LL &y) {
18     if ( b == 0 ) {
19         g = a; x = 1; y = 0;
20     }else {
21         ex_gcd(b, a%b, g, y, x);
22         y -= x * (a/b);
23     }
24 }
25 LL MOD(LL x, LL n) {
26     return (x % n + n) % n;
27 }
28 LL inv(LL a, LL n) {
29     LL x,y,g;
30     ex_gcd(a,n,g,x,y);
31     return g == 1 ?  MOD(x,n) : -1;
32 }
33 LL pow_mod(LL a, LL k, LL p) {
34     LL ret = 1, tmp = a % p;
35     for (; k; k >>= 1) {
36         if (k & 1) ret = ret * tmp % p;
37         tmp = tmp *tmp % p;
38     }
39     return ret;
40 }
41 
42 void init(){
43     memset(num,0,sizeof(num));
44     for (int i = 1; i <= n; i++) {
45         num[a[i]]++;
46     }
47     int e = n - k;
48     c[e] = 1;
49     for (int i = e+1; i <= n; i++) {
50         c[i] = c[i-1] * i % Mod * inv(i - e, Mod) % Mod;
51     }
52 }
53 LL ans[N];
54 void solve(){
55     init();
56     memset(ans, 0, sizeof(ans));
57     int e = n - k;
58     for (int i = m; i >= 1; i--) {
59         int cnt = 0;
60         LL s = 0;
61         for (int j = 1; j * i <= m; j++) {
62             cnt += num[j * i];
63             if (j > 1) s += ans[j * i];
64         }
65         if (cnt >= e) {
66             ans[i] = c[cnt] * pow_mod( m/i-1, cnt-e, Mod) % Mod * pow_mod(m/i, n-cnt, Mod) % Mod;
67             ans[i] = MOD(ans[i] - s, Mod);
68         }
69     }
70     for (int i = 1; i <= m; i++) {
71         printf("%I64d%c",ans[i],i == m ? '\n' : ' ');
72     }
73 }
74 int main(){
75 
76     while (~scanf("%d%d%d",&n,&m,&k)) {
77         for (int i = 1; i <= n; i++) {
78             scanf("%d",a+i);
79         }
80         solve();
81     }
82     return 0;
83 }
View Code

 

 hdu 4669

题意:给一个循环的序列,求子序列组成的数字mod K == 0 的个数;

分析:n*k的DP;

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cstdlib>
 7 #include<cmath>
 8 using namespace std;
 9 typedef long long LL;
10 const int N = 50000+10;
11 int n,k;
12 int a[N];
13 int dp[2][250];
14 int p[N],b[N*5];
15 void init(){
16     for (int i = 1; i <= n; i++) {
17         int t = a[i];
18         int c = 0;
19         while (t) {
20             t /= 10;
21             c++;
22         }
23         p[i] = c;
24     }
25     b[0] = 1;
26     for (int i = 1; i <= n*5; i++) {
27         b[i] = b[i-1]*10%k;
28     }
29 }
30 void solve(){
31     memset(dp,0,sizeof(dp));
32     int pos = 0;
33     LL ret = 0;
34     init();
35     for (int i = 1; i <= n; i++) {
36         for (int j = 0; j < k; j++) {
37             dp[pos^1][(j*b[p[i]]+a[i])%k] += dp[pos][j];
38         }
39         memset(dp[pos],0,sizeof(dp[pos]));
40         dp[pos^1][a[i]%k] += 1;
41         pos ^= 1;
42     }
43     int sum = 0;
44     int tp = 0;
45     for (int i = 1; i <= n; i++) {
46         sum = (sum*b[p[i]] + a[i]) % k;
47         tp += p[i];
48     }
49     for (int i = 1; i <= n; i++) {
50         dp[pos][sum]--;
51         for (int j= 0; j < k; j++) {
52             dp[pos^1][(j*b[p[i]]+a[i])%k] += dp[pos][j];
53         }
54         memset(dp[pos],0,sizeof(dp[pos]));
55         dp[pos^1][a[i]%k] += 1;
56         ret += dp[pos^1][0] ;
57         pos ^= 1;
58         sum = (sum - a[i]*b[tp - p[i]]%k + k) % k;
59         sum = (sum * b[p[i]] + a[i]) % k;
60     }
61     printf("%I64d\n",ret);
62 
63 }
64 int main(){
65     while (~scanf("%d%d",&n,&k)) {
66         for (int i = 1; i <= n; i++) {
67             scanf("%d",a+i);
68         }
69         solve();
70     }
71 
72     return 0;
73 }
View Code

 

hdu 4671

题意:n个服务器m个数据库,每个数据库都有一个服务器的优先级,如果当前服务器没有broken,那么当前数据库就在当前服务器上工作,问任意一个服务器崩溃后是否平衡,

平衡的定义是相邻两个服务器上工作的数据库个数差的绝对值小于等于1.

分析:对于n < m 的情况,每次枚举i服务器奔溃后,决定原先分配给该服务器的数据库的去向,按照少先的的原则,直接for;

其他情况都有固定解;

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<vector>
 8 #include<set>
 9 using namespace std;
10 const int N = 100+10;
11 int n,m;
12 int a[N][N];
13 int cnt[N],cnt2[N];
14 void fillall(int x) {
15     bool vis[N];
16     memset(vis,0,sizeof(vis));
17     vis[a[x][0]] = vis[a[x][1]] = 1;
18     int i = 2, j;
19     for (j = 1; j <= n; j++) {
20         if (vis[j] == 0) {
21             vis[j] = 1;
22             a[x][i++] = j;
23         }
24     }
25 }
26 int main(){
27     while (~scanf("%d%d",&n,&m)) {
28         if (n > m) {
29             int c = 1;
30             for (int i = 0; i < 2; i++) {
31                 for (int j = 0; j < m; j++) {
32                     a[j][i] = c++;
33                     if (i == 1) a[j][i] = m+1;
34                     if (c == n+1) c = 1;
35                 }
36             }
37         }else if (n == m) {
38             for (int i = 0; i < 2; i++) {
39                 int c = i+1;
40                 for (int j = 0; j < m; j++) {
41                     a[j][i] = c++;
42                     if (c == n+1) c = 1;
43                 }
44             }
45         }else if (n < m) {
46             memset(a, 0, sizeof(a));
47             memset(cnt, 0, sizeof(cnt));
48             int c = 1;
49             for (int j = 0; j < m; j++) {
50                 cnt[c] ++;
51                 a[j][0] = c++;
52                 if (c == n+1) c = 1;
53             }
54             for (int j = 1; j <= m; j++) {
55                 for (int k = 1; k <= n; k++) {
56                     cnt2[k] = cnt[k];
57                 }
58                 for (int i = 0; i < cnt[j]; i++) {
59                     int d = -1;
60                     for (int k = 1; k <= n; k++) if (k != j){
61                         if (d == -1 || cnt2[k] < cnt2[d]) d = k;
62                     }
63                     for (int k = 0; k < m; k++) {
64                         if (a[k][0] == j && a[k][1] == 0) {
65                             a[k][1] = d;
66                             cnt2[d]++;
67                             break;
68                         }
69                     }
70                 }
71             }
72         }
73         for (int i = 0; i < m; i++) fillall(i);
74         for (int i = 0; i < m; i++) {
75             for (int j =0; j < n; j++) {
76                 printf("%d%c",a[i][j],j == n-1 ? '\n' : ' ');
77             }
78         }
79 
80     }
81 
82     return 0;
83 }
View Code

 

posted @ 2013-08-13 22:38  Rabbit_hair  阅读(306)  评论(0)    收藏  举报