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 ",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 }
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 ",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 ",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 }
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 ? ' ' : ' '); 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 }
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 ",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 }
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 ? ' ' : ' '); 77 } 78 } 79 80 } 81 82 return 0; 83 }