这次实验室淘汰赛打完之后由于太菜我们还被学长训了一顿,反思很多,痛定思痛,总结了一下自己的不足,有的题比赛时就是想不出以至于挂机,但是第二天早上补题时看一眼就想出来了,很多原因, 牢记教训。
找规律,发现和二进制有某种联系。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MAXM 256 + 10
#define MAXN 100 + 10
using namespace std;
typedef long long ll;
ll k, n;
ll get(ll n)
{
ll ans = 0, dig = 1;
while(n){
ans += (n & 1) * dig;
dig *= 10;
n >>= 1;
}
return ans;
}
int main()
{
scanf("%lld %lld", &k, &n);
ll temp = get(n);
ll ans = 0, dig = 0;
while(temp){
if(temp % 10) ans += pow(k, dig);
temp /= 10;
dig ++;
}
printf("%lld\n", ans);
}
/*
The WAM is F**KING interesting .
*/
/**************************************************************
Problem: 1269
User: 1707004444
Language: C++
Result: 正确
Time:0 ms
Memory:2204 kb
****************************************************************/
可以将子问题转化为01背包问题,然后dfs枚举状态,枚举方法时注意不要在dfs里面放for循环枚举,具体看代码注释部分。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 2800 + 10
#define MAXN 28 + 10
using namespace std;
typedef long long ll;
int n, m;
int w[MAXN], vis[MAXN];
int dp[MAXM];
int total, ans;
void deal(int now, int num)
{
if(now > n) return ;
if(num == 0){
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 0; i < n; i ++){
if(!vis[i]){
for(int j = total; j >= w[i]; j --){
dp[j] |= dp[j-w[i]];
}
}
}
int temp = 0;
for(int i = 1; i <= total; i ++)
if(dp[i]) temp ++;
ans = max(ans, temp);
return ;
}
/*
这样跑一遍会超时
for(int i = 0; i < n; i ++){
if(!vis[i]){
vis[i] = 1;
deal(num - 1);
vis[i] = 0;
}
}
*/
deal(now + 1, num); //不剔除该学生
vis[now] = 1; //剔除该学生
deal(now + 1, num - 1);
vis[now] = 0;
}
int main()
{
scanf("%d %d", &n, &m);
for(int i = 0; i < n; i ++) scanf("%d", &w[i]), total += w[i];
deal(0, m);
printf("%d\n", ans);
}
/*
The WAM is F**KING interesting .
*/
/**************************************************************
Problem: 1268
User: 1707004444
Language: C++
Result: 正确
Time:796 ms
Memory:2032 kb
****************************************************************/
动态规划。dp[ i ][ a[ i ] ] 保存的是第 i 位取 a[ i ] 时的最优解。
dp[i][a[i]]=dp[i-1][a[i-1]]+score[a[i-1]][a[i]] when a[i] != -1 && a[i-1] != -1
dp[ i ][ a[ i ] ] = dp[i][a[i]]=max(dp[i][a[i]],dp[i-1][j]+score[j][a[i]]) when a[i] != -1 && a[i-1] == -1
dp[i][j]=max(dp[i][j],dp[i-1][a[i-1]]+score[a[i-1]][j]) when a[i] == -1 && a[i-1] != -1
dp[i][j]=max(dp[i][j],dp[i-1][k]+score[k][j]) when a[i] == -1 && a[i-1] == -1
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 200 + 10
#define MAXN 1000 + 10
using namespace std;
typedef long long ll;
int t, n, m;
int f[MAXM][MAXM];
int a[MAXN];
int dp[MAXN][MAXM];
int main()
{
scanf("%d", &t);
while(t --){
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i ++)
for(int j = 1; j <= m; j ++)
scanf("%d", &f[i][j]);
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
memset(dp, 0, sizeof(dp));
for(int i = 2; i <= n; i ++){
if(a[i-1] != -1 && a[i] != -1){
dp[i][a[i]] = dp[i-1][a[i-1]] + f[a[i-1]][a[i]];
}
else if(a[i-1] != -1 && a[i] == -1){
for(int j = 1; j <= m; j ++){
dp[i][j] = max(dp[i][j], dp[i-1][a[i-1]] + f[a[i-1]][j]);
}
}
else if(a[i-1] == -1 && a[i] != -1){
for(int j = 1; j <= m; j ++){
dp[i][a[i]] = max(dp[i][a[i]], dp[i-1][j] + f[j][a[i]]);
}
}
else{
for(int j = 1; j <= m; j ++){
for(int k = 1; k <= m; k ++){
dp[i][j] = max(dp[i][j], dp[i-1][k] + f[k][j]);
}
}
}
}
int ans = 0;
for(int i = 1; i <= m; i ++)
ans = max(ans, dp[n][i]);
printf("%d\n", ans);
}
}
/*
The WAM is F**KING interesting .
*/
/**************************************************************
Problem: 1267
User: 1707004444
Language: C++
Result: 正确
Time:436 ms
Memory:3024 kb
****************************************************************/
树状数组板子题
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 100000 + 10
using namespace std;
typedef long long ll;
int tree[MAXN], vis[MAXN];
int n;
void add(int k, int num)
{
while(k <= MAXN){
tree[k] += num;
k += k & -k;
}
}
int sum(int k){
int ans = 0;
while(k){
ans += tree[k];
k -= k & -k;
}
return ans;
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++){
int temp; scanf("%d", &temp);
add(temp, 1);
vis[temp] ++;
int ans = sum(temp);
ans -= (vis[temp] - 1);
printf("%d%c", ans, i == n - 1 ? '\n' : ' ');
}
}
/*
The WAM is F**KING interesting .
*/
/**************************************************************
Problem: 1270
User: 1707004444
Language: C++
Result: 正确
Time:264 ms
Memory:2800 kb
****************************************************************/
对于每个非叶子节点,如果他和他的所有叶子子节点满足条件,那么这棵树就满足条件。bfs每次把子节点不是叶子节点的压入队列。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 2000000 + 10
using namespace std;
typedef long long ll;
vector<int> G[MAXN];
int main()
{
int n; scanf("%d", &n);
for(int i = 1; i < n; i ++){
int a, b; scanf("%d %d", &a, &b);
G[a].push_back(b);
}
queue<int> Q;
Q.push(1);
int ans = 0;
while(!Q.empty()){
int fro = Q.front();
Q.pop();
int son = 0;
for(int i = 0; i < G[fro].size(); i ++){
if(G[G[fro][i]].size() == 0)
son ++;
else{
Q.push(G[fro][i]);
}
}
ans += (son + 1) / 2;
}
printf("%d\n", ans);
}
/*
The WAM is F**KING interesting .
*/
/**************************************************************
Problem: 1265
User: 1707004444
Language: C++
Result: 正确
Time:560 ms
Memory:111464 kb
****************************************************************/
优先队列。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 100000 + 10
using namespace std;
typedef long long ll;
struct node{
int a, b, c;
int x;
int total;
bool operator < (const node &a) const{
return total > a.total;
}
}no[MAXN];
int deal(node n)
{
return n.a * n.x * n.x + n.b * n.x + n.c;
}
int main()
{
int n, m; scanf("%d %d", &n, &m);
priority_queue<node> Q;
for(int i = 0; i < n; i ++){
scanf("%d %d %d", &no[i].a, &no[i].b, &no[i].c);
no[i].x = 1; no[i].total = deal(no[i]);
Q.push(no[i]);
}
int ans = 0;
while(m --){
node temp = Q.top();
Q.pop();
ans += temp.total;
temp.x ++;
temp.total = deal(temp);
Q.push(temp);
}
printf("%d\n", ans);
}
/*
The WAM is F**KING interesting .
*/
/**************************************************************
Problem: 1264
User: 1707004444
Language: C++
Result: 正确
Time:40 ms
Memory:7892 kb
****************************************************************/
带权并查集。将每个节点的父亲和到父亲的距离用数组保存下来。分情况合并,具体看代码。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 5 + 10
#define MAXN 50000 + 10
using namespace std;
typedef long long ll;
int father[MAXN] = {0};
int d[MAXN] = {0}, f = 0, ans = 0;
int get(int x)
{
if(father[x] == x) return x;
f += d[x];
return get(father[x]);
}
void unions(int x, int y, int dd)
{
f = 0; int r_x = get(x); int fx = f;
f = 0; int r_y = get(y); int fy = f;
if(r_x == r_y){
if(fx - fy != dd){
ans ++;
return ;
}
}
else{
if(fx >= fy + dd){
father[r_y] = r_x;
d[r_y] = fx - dd - fy;
}
else{
if(fx > dd){
father[r_x] = r_y;
d[r_x] = dd + fy - fx;
}
else{
father[r_x] = y;
d[r_x] = dd - fx;
}
}
}
}
int main()
{
int n, m; scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i ++) father[i] = i;
for(int i = 0; i < m; i ++){
int a, b, x; scanf("%d %d %d", &a, &b, &x);
unions(a, b, x);
}
printf("%d\n", ans);
}
/*
The WAM is F**KING interesting .
*/
/**************************************************************
Problem: 1275
User: 1707004444
Language: C++
Result: 正确
Time:40 ms
Memory:2408 kb
****************************************************************/