2018 Multi-University Training Contest 5__全部题解+标程:
https://blog.csdn.net/scar_halo/article/details/81458001
1005 Everything Has Changed
Edward is a worker for Aluminum Cyclic Machinery. His work is operating mechanical arms to cut out designed models. Here is a brief introduction of his work.
Assume the operating plane as a two-dimensional coordinate system. At first, there is a disc with center coordinates (0,0) and radius R. Then, m mechanical arms will cut and erase everything within its area of influence simultaneously, the i-th area of which is a circle with center coordinates (xi,yi) and radius ri (i=1,2,⋯,m). In order to obtain considerable models, it is guaranteed that every two cutting areas have no intersection and no cutting area contains the whole disc.
Your task is to determine the perimeter of the remaining area of the disc excluding internal perimeter.
Here is an illustration of the sample, in which the red curve is counted but the green curve is not.
Input
The first line contains one integer T, indicating the number of test cases.
The following lines describe all the test cases. For each test case:
The first line contains two integers m and R.
The i-th line of the following m lines contains three integers xi,yi and ri, indicating a cutting area.
1≤T≤1000, 1≤m≤100, −1000≤xi,yi≤1000, 1≤R,ri≤1000 (i=1,2,⋯,m).
Output
For each test case, print the perimeter of the remaining area in one line. Your answer is considered correct if its absolute or relative error does not exceed 10−6.
Formally, let your answer be a and the jury's answer be b. Your answer is considered correct if |a−b|max(1,|b|)≤10−6.
Sample Input
1
4 10
6 3 5
10 -4 3
-2 -4 4
0 9 1
题意:在一个坐标圆心(0,0)半径为R的圆上切下去m个圆,问剩下的圆的部分外圈的周长
题解:判断两个圆的位置,然后利用余弦定理求圆心角,加减弧长就可以
代码:
#include<iostream>
#include<stdio.h>
#include<math.h>
#define PI acos(-1.0)
using namespace std;
int main()
{
int t;
scanf("%d",&t);
double a1,b1,r1,a2,b2,r2,d;
double A1,A2,s1,s2,s;
while(t--)
{
double ans=0;
a1=b1=0;
int hh;
scanf("%d %lf",&hh,&r1);
ans=2*PI*r1;
for(int i=1;i<=hh;i++)
{
scanf("%lf%lf%lf",&a2,&b2,&r2);
d=sqrt((a2)*(a2)+(b2)*(b2));
if(d>=r1+r2)
{
ans+=0;
continue;
}
else
if(d==fabs(r1-r2))//内切
{
ans+=PI*r2*2;
continue;
}
else
if(d<r1+r2&&d>fabs(r1-r2))//两个圆相交的情况
{
A1=2*acos((d*d+r1*r1-r2*r2)/(2*d*r1));
A2=2*acos((d*d+r2*r2-r1*r1)/(2*d*r2));
ans-=A1*r1;
ans+=A2*r2;
continue;
}
}
printf("%.20lf\n",ans);
}
return 0;
}
1002 Beautiful Now
Problem Description
Anton has a positive integer n, however, it quite looks like a mess, so he wants to make it beautiful after k swaps of digits.
Let the decimal representation of n as (x1x2⋯xm)10 satisfying that 1≤x1≤9, 0≤xi≤9 (2≤i≤m), which means n=∑mi=1xi10m−i. In each swap, Anton can select two digits xi and xj (1≤i≤j≤m) and then swap them if the integer after this swap has no leading zero.
Could you please tell him the minimum integer and the maximum integer he can obtain after k swaps?
Input
The first line contains one integer T, indicating the number of test cases.
Each of the following T lines describes a test case and contains two space-separated integers n and k.
1≤T≤100, 1≤n,k≤109.
Output
For each test case, print in one line the minimum integer and the maximum integer which are separated by one space.
Sample Input
5
12 1
213 2
998244353 1
998244353 2
998244353 3
Sample output
12 21
123 321
298944353 998544323
238944359 998544332
233944859 998544332
题目:
给你一个字符串,交换最多k次,找出里面最小的字符串和最大的字符串
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include <sstream>
#define inf 800000000000
#define ll long long
#define mod 1000000007
using namespace std;
string maxs,mins;
int n;
/**求最小深搜**/
void dfs1(int now,int k,string st) //顶指针,交换剩余次数,当前字符串
{
int i,minn;
if(k==0||now==n)
{
if(st<mins)
{
mins=st;
}
return;
}
if(now==0) //第一位,此时不能有前导零
{
minn=now;
for(i=now+1;i<n;i++)
{
if(st[i]!='0'&&st[i]<=st[minn]&&st[i]!=st[now])
{
minn=i;
}
}
if(minn!=now)
{
for(i=now+1;i<n;i++)
{
if(st[i]==st[minn])
{
string s=st;
swap(s[now],s[i]);
dfs1(now+1,k-1,s); //有交换情况,交换
}
}
}
else
dfs1(now+1,k,st); //无交换情况,不交换,顶指针进一位
}
else// 非第一位
{
minn=now;
for(i=now+1;i<n;i++)
{
if(st[i]<=st[minn]&&st[i]!=st[now])
{
minn=i;
}
}
if(minn!=now)
{
for(i=now+1;i<n;i++)
{
if(st[i]==st[minn])
{
string s=st;
swap(s[now],s[i]);
dfs1(now+1,k-1,s);
}
}
}
else
dfs1(now+1,k,st);
}
return;
}
/**求最大深搜,和上面一样**/
void dfs2(int now,int k,string st)
{
int i,maxn;
if(k==0||now==n)
{
if(st>maxs)
{
maxs=st;
}
return;
}
if(now==0)
{
maxn=now;
for(i=now+1;i<n;i++)
{
if(st[i]!='0'&&st[i]>=st[maxn]&&st[i]!=st[now])
{
maxn=i;
}
}
if(maxn!=now)
{
for(i=now+1;i<n;i++)
{
if(st[i]==st[maxn])
{
string s=st;
swap(s[now],s[i]);
dfs2(now+1,k-1,s);
}
}
}
else
dfs2(now+1,k,st);
}
else
{
maxn=now;
for(i=now+1;i<n;i++)
{
if(st[i]>=st[maxn]&&st[i]!=st[now])
{
maxn=i;
}
}
if(maxn!=now)
{
for(i=now+1;i<n;i++)
{
if(st[i]==st[maxn])
{
string s=st;
swap(s[now],s[i]);
dfs2(now+1,k-1,s);
}
}
}
else
dfs2(now+1,k,st);
}
return;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int k;
string s;
cin>>s;
scanf("%d",&k);
mins=s;
n=s.length();
dfs1(0,k,s);
cout<<mins<<" ";
maxs=s;
dfs2(0,k,s);
cout<<maxs<<endl;
}
}
1007Glad You Came
Steve has an integer array a of length n (1-based). He assigned all the elements as zero at the beginning. After that, he made m operations, each of which is to update an interval of a with some value. You need to figure out ⨁ni=1(i⋅ai) after all his operations are finished, where ⨁ means the bitwise exclusive-OR operator.
In order to avoid huge input data, these operations are encrypted through some particular approach.
There are three unsigned 32-bit integers X,Y and Z which have initial values given by the input. A random number generator function is described as following, where ∧ means the bitwise exclusive-OR operator, << means the bitwise left shift operator and >> means the bitwise right shift operator. Note that function would change the values of X,Y and Z after calling.
Let the i-th result value of calling the above function as fi (i=1,2,⋯,3m). The i-th operation of Steve is to update aj as vi if aj<vi (j=li,li+1,⋯,ri), where
⎧⎩⎨⎪⎪lirivi=min((f3i−2modn)+1,(f3i−1modn)+1)=max((f3i−2modn)+1,(f3i−1modn)+1)=f3imod230(i=1,2,⋯,m).
Input
The first line contains one integer T, indicating the number of test cases.
Each of the following T lines describes a test case and contains five space-separated integers n,m,X,Y and Z.
1≤T≤100, 1≤n≤105, 1≤m≤5⋅106, 0≤X,Y,Z<230.
It is guaranteed that the sum of n in all the test cases does not exceed 106 and the sum of m in all the test cases does not exceed 5⋅107.
Output
For each test case, output the answer in one line.
Sample Input
4
1 10 100 1000 10000
10 100 1000 10000 100000
100 1000 10000 100000 1000000
1000 10000 100000 1000000 10000000
Sample Output
1031463378
1446334207
351511856
47320301347
Hint
In the first sample, a = [1031463378] after all the operations.
In the second sample, a = [1036205629, 1064909195, 1044643689, 1062944339, 1062944339, 1062944339, 1062944339, 1057472915, 1057472915, 1030626924] after all the operations.
题意:更新区间里面比当前值小的数;
做法:典型的线段树区间,不过用线段树需要剪枝,毕竟线段树比较慢。
还有一个做法是用st,rmq,只需要把查询改成更新,更新改成查询就好了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5+7;
int st[N][20];
int lg[N];
unsigned int x,y,z;
void init(){
lg[1] = 0;
int now = 2;
for(int i = 2;i < N;i ++){
lg[i] = lg[i-1];
if(i > now) lg[i]++,now*=2;
}
}
unsigned int get(){
x = x^(x<<11);
x = x^(x>>4);
x = x^(x<<5);
x = x^(x>>14);
unsigned int w = x^y^z;
x = y;
y = z;
z = w;
return z;
}
void update(int l,int r,int x){
int l2 = lg[r-l+1];
st[l][l2] = max(st[l][l2],x);
st[r-(1<<l2)+1][l2] = max(st[r-(1<<l2)+1][l2],x);
}
long long get(int n){
int l2 = lg[n];
for(int i = l2;i >= 1;i --){
for(int j = 1;j <= n;j ++){
if(j+(1<<i)> n+1) break;
st[j][i-1] = max(st[j][i-1],st[j][i]);
st[j+(1<<(i-1))][i-1] = max(st[j+(1<<(i-1))][i-1],st[j][i]);
}
}
long long ret = 0;
for(int i = 1;i <= n;i ++){
ret ^= 1LL*i*st[i][0];
}
return ret;
}
void set0(int n){
int l2 = lg[n];
for(int i = 0;i <= l2;i ++){
for(int j = 1;j <= n;j ++) st[j][i] = 0;
}
}
int main(){
init();
int T;
cin >> T;
while(T--){
//memset(st,0,sizeof(st));
int n,m;
scanf("%d %d",&n,&m);
set0(n);
scanf("%u %u %u",&x,&y,&z);
for(int i = 1;i <= m;i ++){
int l = get()%n+1,r = get()%n+1,v =get()%(1<<30);
if(l > r) swap(l,r);
update(l,r,v);
}
printf("%lld\n",get(n));
}
return 0;
}