傳送門:https://ac.nowcoder.com/acm/contest/373#question
A. 翻硬幣問題
題解:很明顯如果不能一次拿走,那麼總是能翻轉其中一枚硬幣來破壞與的奇偶性。
代碼
#include<bits/stdc++.h>
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
using namespace std;
//1 1 1 1 1
//0 0 0 1 1
//0 1 1 1 1
//
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
ios::sync_with_stdio(false); cin.tie(0);
int n,m;
int T;
cin >> T;
while(T--) {
cin >> n >> m;
cout << ((n == m)? "Yes" : "No")<< endl;
}
return 0;
}
B. 666RPG
題意:兩個操作。
- 每次將分數加
- 將當前總分乘以
問:給出序列,多少種方案使得最後的分數爲。
題解:表示前個數可以湊成分數爲的方案總數。顯然每次有兩個狀態轉移,也就是會從和轉移過來。因此
發現這樣會。再看方程,每次只會從轉移過來,因此,滾動數組解決。
代碼
#include<bits/stdc++.h>
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
using namespace std;
typedef long long LL;
const int N = 300 * 666, mod = 1e8 + 7;
LL dp[2][N * 10];
int a[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
ios::sync_with_stdio(false); cin.tie(0);
//dp[i][j] = dp[i - 1][j - a[i]] + dp[i - 1][-j]
int n, cur = 0;
cin >> n;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
}
int dx = N + 666;
dp[1][dx] = 1;
for(int i = 1; i <= n; ++i) {
for(int j = -N; j <= N; ++j) {
if(j == 666) continue;
dp[cur][j + dx] = (dp[cur ^ 1][j - a[i] + dx] + dp[cur ^ 1][-j + dx]) % mod;
}
cur ^= 1;
}
cout << dp[cur ^ 1][-666 + dx] << endl;
return 0;
}
C. 抓捕盜竊犯
題解:可以知道會形成很多個環,在環上任意建一點哨卡即可,最終的收益是環上所有點,因此我們預處理出所有連通塊(我這裏用的並查集),然後排序取前大的即可。
代碼
#include<bits/stdc++.h>
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
using namespace std;
const int N = 1E5+10;
typedef long long LL;
int f[N],node[N];
LL a[N], sum[N];
vector<int> E[N];
int getf(int v)
{
if(f[v] == v) return v;
return f[v] = getf(f[v]);
}
void mrg(int u,int v)
{
int p = getf(u);
int q = getf(v);
if(p != q) {
f[p] = q;
}
}
vector<LL> value;
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
ios::sync_with_stdio(false); cin.tie(0);
int n,m;
cin >> n >> m;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
f[i] = i;
}
int v;
for(int i = 1; i <= n; ++i) {
cin >> v;
mrg(i,v);
}
for(int i = 1; i <= n; ++i) {
E[getf(i)].push_back(a[i]);
}
LL ans = 0;
for(int i = 1; i <= n; ++i) {
if(f[i] == i) {
LL SUM = 0;
for(auto w : E[i]) {
SUM += w;
}
value.push_back(SUM);
}
}
sort(value.begin(),value.end(),greater<LL>());
for(int i = 0; i < m && i < value.size(); ++i) {
ans += value[i];
}
cout << ans << endl;
return 0;
}
D. 最小相似度
題意:求的最小值,表示和異或後的的個數。
題解:emmmm,表示fwt就做過一道題,不太會。
但是大小隻有,狀態只有個,我們考慮給出的個串到每個狀態的距離的最小距離,串到串的花費爲改變的位數,我們讓這個最小距離最大化,然後用減去這個最大化的最小距離,就是這個串與串最大距離的最小值。但是這樣做是的,因此用多源處理即可,複雜度爲節點個數,即。
代碼
#include<bits/stdc++.h>
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
using namespace std;
int dis[1 << 21];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
ios::sync_with_stdio(false); cin.tie(0);
int n,m;
memset(dis, -1, sizeof dis);
string s;
cin >> n >> m;
queue<int> q;
for(int i = 0; i < n; ++i) {
cin >> s;
int t = 0;
for(int j = 0; j < m; ++j) {
t |= (1 << j) * (s[j] == '1');
}
if(dis[t] == -1) {
dis[t] = 0;
q.push(t);
}
}
int ans = 0;
while(!q.empty()) {
int cur = q.front(); q.pop();
ans = max(ans, dis[cur]);
for(int i = 0; i < m; ++i) {
if(dis[cur ^ (1 << i)] == -1) {
dis[cur ^ (1 << i)] = dis[cur] + 1;
q.push(cur ^ (1 << i));
}
}
}
cout << m - ans << endl;
return 0;
}
E. 球的體積並
題解:正好寒假秦皇島camp做過一道球的體積交的題,嘿嘿。直接隨便copy了一份板子就過了~
判斷一下兩個球是相交還是相離還是相切即可。
代碼
#include<bits/stdc++.h>
using namespace std;
double Pow(double x){ return x*x; }
double san(double x){ return x*x*x; }
const double PI = acos(-1);
struct node {
double x, y, z, r;
void get() { scanf("%lf%lf%lf%lf", &x, &y, &z, &r); }
double dis(node a) {
return sqrt(Pow(x - a.x) + Pow(y - a.y) + Pow(z - a.z));
}
double get_aera(node a) {
double d = dis(a);
double x1 = (a.r * a.r - r * r + d * d) / 2 / d;
double x2 = d - x1;
double h1 = r - x2;
double h2 = a.r - x1;
return PI / 3 * (3 * r - h1) * h1 * h1
+ PI / 3 * (3 * a.r - h2) * h2 * h2;
}
}a[2];
int main() {
a[0].get();
a[1].get();
double ans = 0;
double p = 4.0 / 3 * PI * san(a[1].r), q = 4.0 / 3 * PI * san(a[0].r);
if (a[0].dis(a[1]) <= fabs(a[0].r - a[1].r)) {
ans = max(p, q);
} else if (a[0].dis(a[1]) >= a[0].r + a[1].r) {
ans = p + q;
} else {
ans = p + q - a[0].get_aera(a[1]);
}
printf("%.7f\n", ans);
}