Topcoder SRM 606 div1题解

打卡!

Easy(250pts):

题目大意:一个人心中想了一个数,另一个人进行了n次猜测,每一次第一个人都会告诉他实际的数和猜测的数的差的绝对值是多少,现在告诉你所有的猜测和所有的差,要求你判断心中所想的数是多少,如果无解输出-1,如果有多个解输出-2。数据满足n<=50,想的那个数在[1,10^9]中。

这题是不是很简单呀~

首先通过第一次我们就最多确定两个数了,

然后分别带到后面去看一下就可以了,

时间复杂度O(n),代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n,ans1,ans2;
 4 bool check1=true,check2=true;
 5 class EllysNumberGuessing
 6 {
 7     public:
 8     int getNumber(vector <int> guesses, vector <int> answers)
 9     {
10         n=guesses.size();
11         ans1=guesses[0]+answers[0];
12         ans2=guesses[0]-answers[0];
13         for (int i=1;i<n;i++)
14         {
15             if (abs(ans1-guesses[i])!=answers[i]) check1=false;
16             if (abs(ans2-guesses[i])!=answers[i]) check2=false;
17         }
18         if (ans1<1||ans1>1000000000) check1=false;
19         if (ans2<1||ans2>1000000000) check2=false;
20         if (check1&&check2) return -1;
21         if ((!check1)&&(!check2)) return -2;
22         if (check1) return ans1;
23         if (check2) return ans2;
24     }
25 };

Medium(450pts):

题目大意:有n个公司,每个公司去了好多好多人来比赛,每个人的名字是一个小于M的非负整数。现在要两两组队,并且尽可能有更多的组使得同一组的两个人的名字不一样,求最多能组多少对。数据满足n<=50,M<=1073741824且M是一个2的幂次,需要注意的是本题空间限制只有16MB。

矣~这题不是浙江省选期间和吕爷爷讨论的一个ACM题目嘛。。。然而空间只有16MB。。。

我们先不考虑这个16MB的限制,回到题目的本质。

假设一共有x个人,

考虑出现次数最多的一个名字,我们假设它出现了y次。

如果y<=(x+1)/2,那么答案一定就是x/2;

如果y>(x+1)/2,那么答案一定就是x-y。

于是这样原题就做完了。

考虑那个恶心的16MB,我们显然不能把所有的名字全部预处理出来,不然就爆炸啦~

我们发现我们只需要比较出现最多的数是否出现了超过一半,

这个时候我们就想到了杜教主冬令营上讲的一个并行算法题目的做法,

设当前出现次数最多的为x,出现了y次。

如果当前的数等于x,那么y加上1;

如果当前的数不等于x,如果y=0那么x更换成新的值,不然的话y减去1.

在最后我们还需要检验一下当前的数是否超过了一半,这样我们就可以在O(n)的时间复杂度内用额外O(1)的空间复杂度完成任务。

于是顺利12MB卡过~

时间复杂度O(n),代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n;
 4 class EllysPairing
 5 {
 6     public:
 7     int getMax(int M, vector <int> count, vector <int> first, vector <int> mult, vector <int> add)
 8     {
 9 //now is the name apeears most while cnt represents how many times it appears
10 //tot means how many people are there in all
11         int now=0,cnt=0,tot=0,t;
12         n=count.size();
13         for (int i=0;i<n;i++)
14         {
15             t=first[i],tot+=count[i];
16             for (int j=0;j<count[i];j++)
17             {
18                 if (t==now) ++cnt;
19                 else
20                 {
21                     if (cnt==0) now=t,cnt=1;
22                     else --cnt;
23                 }
24                 if (j<count[i]-1) t=(t*mult[i]+add[i])&(M-1);
25             }
26         }
27         cnt=0;
28         for (int i=0;i<n;i++)
29         {
30             t=first[i];
31             for (int j=0;j<count[i];j++)
32             {
33                 if (t==now) ++cnt;
34                 if (j<count[i]-1) t=(t*mult[i]+add[i])&(M-1);
35             }
36         }
37         if (cnt<=(tot+1)/2) return tot/2;
38         return tot-cnt;
39     }
40 };

Hard(950pts):

题目大意:给出三维空间中的n个点,从中选出若干个点,如果这些点都在某一个立方体的8个顶点上,那么这些点就称为一个好的组合,问一共有多少个好的组合。数据满足n<=50,n个点互不相同且一定都是整点。需要注意的是,立方体是可以旋转的。

首先我们分析一下,所有满足条件的立方体不是很多,所以最后的答案也不是很多,直接搜索即可。

考虑满足条件的立方体,它的边长一定是某两点距离的1倍或1/sqrt(2)倍或1/sqrt(3)倍。(还有可能是0)

于是我们用一个2^n的数来表示每个点是否被加入,于是直接统计答案就可以了。

复杂度O(n^4)(大概吧,反正跑得过),代码如下:

 1 #include <bits/stdc++.h>
 2 #define Maxn 57
 3 using namespace std;
 4 int n;
 5 long long dis[Maxn][Maxn];
 6 multiset<long long> st,ans;
 7 map<long long,bool> vis;
 8 class Subcube
 9 {
10     void dfs(int x, long long state, long long len)
11     {
12 //x means which point is being dealed now
13 //state means the situation of the point(belonged to the cubic or not)
14 //len means the length of an edge of the cubic
15         if (x==n) 
16         {
17             if (!vis[state]) ans.insert(state),vis[state]=true;
18         } else
19         {
20 //x doesn't belong to the cubic
21             dfs(x+1,state,len);
22 //x belongs to the cubic
23             for (int i=0;i<n;i++)
24                 if ((state>>i)%2==1)
25                 {
26                     long long r1=dis[i][x];
27                     if (r1!=len&&r1!=len*2&&r1!=len*3) return;
28                     for (int j=0;j<n;j++)
29                         if (((state>>j)%2==1)&&(j!=i))
30                         {
31                             long long r2=r1+dis[i][j]+dis[j][x];
32                             if (r2!=4*len&&r2!=6*len) return;
33                         }
34                 }
35             dfs(x+1,state+(1LL<<x),len);
36         }
37     }
38     public:
39     long long getCount(vector <int> X, vector <int> Y, vector <int> Z)
40     {
41         n=X.size();
42         st.clear();
43         for (int i=0;i<n;i++)
44             for (int j=0;j<n;j++)
45                 dis[i][j]=1LL*(X[i]-X[j])*(X[i]-X[j])+1LL*(Y[i]-Y[j])*(Y[i]-Y[j])+1LL*(Z[i]-Z[j])*(Z[i]-Z[j]);
46         for (int i=0;i<n;i++)
47             for (int j=i+1;j<n;j++)
48             {
49                 st.insert(dis[i][j]);
50                 if (dis[i][j]%2==0) st.insert(dis[i][j]/2);
51                 if (dis[i][j]%3==0) st.insert(dis[i][j]/3);
52             }
53         st.insert(0);
54         ans.clear();
55         for (multiset<long long>::iterator it=st.begin();it!=st.end();it++)
56             dfs(0,0,*it);
57         return ans.size()-1;
58     }
59 };
原文地址:https://www.cnblogs.com/Tommyr7/p/6873884.html