下面的题解按照难度排序。
T1
果断枚举坐标就行了 。
时间复杂度是 O
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 205;
double dis[MAXN],x[MAXN],y[MAXN];
int n;
double calc(double X1,double Y1, double X2, double Y2) {
return sqrt((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1));
}
int main() {
cin >> n;
for(int i = 1 ; i <= n ; i ++)
cin >> x[i] >> y[i];
for(int i = 1 ; i <= 200 ; i ++) {
for(int j = 1 ; j <= 200 ; j ++) {
double X = double(i) , Y = double(j);
for(int k = 1 ; k <= n ; k ++)
dis[k] = calc(x[k],y[k],X,Y);
int flag = 0;
for(int k = 1 ; k <= n ; k ++)
if(abs(dis[k] - dis[1]) > 0.0001) flag = 1;
if(flag == 0) {cout << i << " " << j << endl; return 0;}
}
}
cout << "War is cruel.";
return 0;
} T2
观察题目后,不难想到把原数组按照战力从大到小排序。
然后映射,对于排序后的数组映射为每一个数在原数组中的下标。
假设原数组中第 大的是在第
大的后面,那么显然答案是要 + 1的,因为这就得删去第
大的后重新来一轮。
我们发现只需要判断映射后的数组中有多少个 即可。
最后的答案要 + 1,因为无论如何至少要进行一轮。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 8e5 + 50;
bool book[MAXN + MAXN / 4];
int n,A[MAXN];
struct Node {
int data,id;
bool operator < (const Node &Q) {
return Q.data < data;
}
} T[MAXN];
inline int read() {
int x = 0 , flag = 1;
char ch = getchar() ;
for( ; ch > '9' || ch < '0' ; ch = getchar()) ;
for( ; ch >= '0' && ch <= '9' ; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
return x * flag;
}
int main() {
n = read();
for(int i = 1 ; i <= n ; i ++) A[i] = read();
for(int i = 1 ; i <= n ; i ++) T[i].data = A[i] , T[i].id = i;
sort(T + 1 , T + 1 + n );
int Ans = 0;
for(int i = 1 ; i <= n ; i ++) if(T[i].id > T[i + 1].id) Ans ++;
cout << Ans;
return 0;
} T4
不难发现,要求经过的边最少,那么就是一棵生成树。
要求权值最小,那么就是最小生成树。
观察到在一棵树里面能够保证每条边恰好被经过两次(根据欧拉序可知)。
所以最后的答案就是最小生成树的权值 * 2。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 50;
int n,m,cnt = 0;
int start[MAXN],f[MAXN];
struct Edge {
int to,from,w;
} edge[MAXN * 10];
inline int read() {
int x = 0 , flag = 1;
char ch = getchar() ;
for( ; ch > '9' || ch < '0' ; ch = getchar()) ;
for( ; ch >= '0' && ch <= '9' ; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
return x * flag;
}
void add(int u,int v,int w) {
edge[++cnt].from = u;
edge[cnt].to = v;
edge[cnt].w = w;
return ;
}
int find(int x) {
if(f[x] != x) f[x] = find(f[x]);
return f[x];
}
bool cmp(Edge AA, Edge BB) {
return AA.w < BB.w;
}
int main() {
n = read() , m = read();
for(int i = 1 ; i <= n ; i ++) f[i] = i;
for(int i = 1 ; i <= m ; i ++) {
int u = read() , v = read() , w = read();
add(u,v,w);
}
long long Ans = 0;
sort(edge + 1 , edge + 1 + cnt, cmp);
for(int i = 1 ; i <= cnt ; i ++) {
int from = edge[i].from , to = edge[i].to;
if(find(from) != find(to)) {
f[find(from)] = find(to);
Ans += edge[i].w;
}
}
cout << Ans * 2;
return 0;
} T3
我怎么这么菜啊,这道题卡了比较久。。。。但是实际上并不难。
首先考虑,把长度限制按照从小答案排序后,前面的名字无论如何都会对后面的名字产生影响,也就是后面的名字不能与前面的相同。
不妨假装生成一个总的名字集合,不难发现,为了保证名字不重复,前面的名字如果出现了一次的话,后面的就不能再次出现这个名字,于是我们就把这个名字从这个集合里面“删去”,其实也并不是“删去”,而是说我们“假装”把它删去,后面计算答案的时候,都减去这个的贡献就行了。
// Problem: 照看小猫
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11038/C
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int Mod = 77797,MAXN = 1e4 + 50;
int A[MAXN],M[20] = {1},book[15];
int Q[11][MAXN];
int n,sum[20];
int quickpower(int x,int k) {
int ans = 1 , op = x;
while(k) {
if(k & 1ll) ans *= op;
op = op * op;
k >>= 1ll;
}
return ans;
}
signed main() {
cin >> n;
for(int i = 1 ; i <= n ; i ++) cin >> A[i];
for(int i = 1 ; i <= 10 ; i ++) M[i] = M[i - 1] * 26 % Mod;
for(int i = 2 ; i <= 10 ; i ++) M[i] = M[i - 1] + M[i] , M[i] %= Mod;
sort(A + 1 , A + 1 + n);
int Ans = 1;
for(int i = 1 ; i <= n ; i ++) {
if(A[i] < 3 && M[A[i]] - i < 0) {cout << -1 ; return 0;}
// 这里要注意,判断A[i] < 3 是因为如果 A[i] >= 3 的时候,M[A[i]] 就已经大于10000了,可能因为取模的缘故使得M[A[i]] < 10000。
else Ans = (Ans * (M[A[i]] - (i - 1))) % Mod;
}
cout << Ans;
return 0;
} 
京公网安备 11010502036488号