T1 Bus
题意:
小学坐车问题.
解法:
暴力.
代码:
#include <bits/stdc++.h>
using namespace std ;
int a, b, f, k, flag = 1 , ans = 0 , gg;
int x[100000 ];
int main()
{
cin >> a >> b >> f >> k;
x[1 ] = f;
gg = b;
int dai = k;
dai--;
while (dai > 0 )
{
flag++;
x[flag] = (a - f) * 2 ;
dai--;
if (dai > 0 )
{
flag++;
x[flag] = (f * 2 );
}
dai--;
}
flag++;
if (k % 2 != 0 )
x[flag] = (a - f);
else
x[flag] = (f);
for (int i = 1 ; i <= k; i++)
{
if (b >= x[i] + x[i + 1 ])
{
b -= x[i];
}
else if (b >= x[i])
{
ans++;
b = gg;
}
else
{
cout << -1 ;
return 0 ;
}
}
if (b < x[k + 1 ])
{
cout << -1 ;
return 0 ;
}
cout << ans;
return 0 ;
}
小结:
**此类题目水题。**
T2 Make a Permutation!
题意:
现在给出一个n,以及n个数,这n个数范围为1~n。 现在问最少改变几个数能使这n个数成为1~n的全排列,若有多种情况,使全排列的字典序最小。
解法:
暴力.
代码:
#include <bits/stdc++.h>
using namespace std ;
int x[300000 ], y[210000 ], mm[200010 ];
bool z[210000 ];
priority_queue<int > p;
int main()
{
int a, ans = 0 , ee = 0 ;
cin >> a;
for (int i = 1 ; i <= a; i++)
{
cin >> x[i];
y[x[i]]++;
if (y[x[i]] > 1 || x[i] > a)
ans++;
}
cout << ans << endl;
for (int i = 1 ; i <= a; i++)
if (y[i] == 0 )
p.push(i);
while (!p.empty())
{
ee++;
mm[ee] = p.top();
p.pop();
}
for (int i = 1 ; i <= a; i++)
{
if (y[x[i]] > 1 || x[i] > a || x[i] < 1 )
{
if (mm[ee] > x[i] && z[x[i]] == false && x[i] > 0 )
{
z[x[i]] = true ;
}
else if (mm[ee] != x[i])
{
y[x[i]]--;
x[i] = mm[ee];
ee--;
}
}
cout << x[i] << " " ;
}
return 0 ;
}
小结:
**此类题目暴力。**
T3 Fire
题意:
若干个物品暴露在大火中,拯救第i个物品需要消耗ti时间,在di时这个物品就会被烧掉,这个物品的价值为vi,问能救下的物品价值最大是多少。
解法:
背包.
代码:
#include <bits/stdc++.h>
using namespace std ;
#define N 2002
int dp[N], flag, ans;
vector <int > lu[N];
struct line
{
int shi, zhi, yuan, jie;
} x[N];
bool cmp(line x, line y)
{
if (x.jie == y.jie)
return x.shi < y.shi;
else
return x.jie < y.jie;
}
int main()
{
int a;
cin >> a;
for (int i = 1 ; i <= a; i++)
{
cin >> x[i].shi >> x[i].jie >> x[i].zhi;
x[i].yuan = i;
}
sort(x + 1 , x + a + 1 , cmp);
for (int i = 1 ; i <= a; i++)
{
for (int j = x[i].jie - 1 ; j >= x[i].shi; j--)
{
if (dp[j - x[i].shi] + x[i].zhi > dp[j])
{
dp[j] = dp[j - x[i].shi] + x[i].zhi;
lu[j] = lu[j - x[i].shi];
lu[j].push_back(x[i].yuan);
}
}
}
for (int i = 1 ; i <= 2000 ; i++)
{
if (dp[i] > ans)
{
ans = dp[i];
flag = i;
}
}
cout << ans << endl;
cout << lu[flag].size() << endl;
for (int i = 0 ; i < lu[flag].size(); i++)
cout << lu[flag][i] << " " ;
return 0 ;
}
小结:
**此类题目....。**
T4 Marvolo Gaunt’s Ring
题意:
给一个数组,让求p·ai + q·aj + r·a 的最大值(1 ≤ i ≤ j ≤ k ≤ n)
解法:
递推.
代码:
#include <bits/stdc++.h>
using namespace std ;
long long n, p, q, r, P, Q, R, a[100005 ];
main()
{
cin >> n >> p >> q >> r;
for (int i = 1 ; i <= n; i++)
cin >> a[i];
R = r * a[n];
Q = R + q * a[n];
P = Q + p * a[n];
for (int i = n - 1 ; i >= 1 ; i--)
{
R = max(R, r * a[i]);
Q = max(Q, R + q * a[i]);
P = max(P, Q + p * a[i]);
}
cout << P << endl;
}
小结:
**此类题目较易,就是不好调试。**
T5 Helga Hufflepuff’s Cup
题意:
给你一棵树,可以染 m 种颜色,现定义一种特殊的颜色 K ,一棵树上最多能有 X 个特殊颜色。如果一个节点为特殊颜色 K ,那么他相邻的节点的值只能选比 K 小的颜色,问一共有多少种染色方案。
解法:
树形dp.
代码:
#include <cstdio>
long long dp[100001 ][11 ][3 ], mo, ans, f[11 ][3 ];
int n, m, k, n1, nex[200001 ], nn[100001 ];
int mm[200001 ], tot, fa[100001 ], a1, b1;
void tian(int aa, int bb)
{
tot++;
nex[tot] = nn[aa];
nn[aa] = tot;
mm[tot] = bb;
}
void dfs(int x)
{
int aa = nn[x];
dp[x][1 ][1 ] = 1 ;
dp[x][0 ][0 ] = k - 1 ;
dp[x][0 ][2 ] = m - k;
while (aa != 0 )
{
if (fa[x] != mm[aa])
{
fa[mm[aa]] = x;
dfs(mm[aa]);
for (int j = 0 ; j <= 2 ; j++)
for (int i = 0 ; i <= n1; i++)
f[i][j] = 0 ;
for (int i = 0 ; i <= n1; i++)
for (int j = 0 ; j <= i; j++)
{
f[i][1 ] = (f[i][1 ] + dp[x][i - j][1 ] * dp[mm[aa]][j][0 ]) % mo;
f[i][0 ] = (f[i][0 ] + dp[x][i - j][0 ] * (dp[mm[aa]][j][0 ] + dp[mm[aa]][j][1 ] + dp[mm[aa]][j][2 ])) % mo;
f[i][2 ] = (f[i][2 ] + dp[x][i - j][2 ] * (dp[mm[aa]][j][0 ] + dp[mm[aa]][j][2 ])) % mo;
}
for (int j = 0 ; j <= 2 ; j++)
for (int i = 0 ; i <= n1; i++)
dp[x][i][j] = f[i][j];
}
aa = nex[aa];
}
}
int main()
{
scanf ("%d%d" , &n, &m);
mo = 1000000007 ;
for (int i = 1 ; i <= n - 1 ; i++)
{
scanf ("%d%d" , &a1, &b1);
tian(a1, b1);
tian(b1, a1);
}
scanf ("%d%d" , &k, &n1);
fa[1 ] = 1 ;
dfs(1 );
ans = 0 ;
for (int i = 0 ; i <= 2 ; i++)
for (int j = 0 ; j <= n1; j++)
ans = (ans + dp[1 ][j][i]) % mo;
printf ("%I64d\n" , ans);
return 0 ;
}
小结:
**此类题目较难。,好题**
T6 Salazar Slytherin’s Locket
题意:
求[l,r]之间,满足b进制下每个数字都出现偶数次的数有多少个。
解法:
状压dp.
代码:
#include <cstdio>
#include <cstring>
typedef long long LL;
LL q, b, l, r;
LL ans[11 ][70 ][2049 ];
LL w[70 ];
LL dp(LL mn, LL nm, LL zz, bool mm, bool nn)
{
if (nm < 1 )
return !zz;
if (!nn && !mm && ans[mn][nm][zz] != -1 )
return ans[mn][nm][zz];
LL i, res = 0 , start = mm ? 1 : 0 , end = nn ? w[nm] : (mn - 1 );
for (i = start; i <= end; i++)
res += dp(mn, nm - 1 , zz ^ (1 << i), 0 , nn && i == w[nm]);
if (!nn && !mm)
ans[mn][nm][zz] = res;
return res;
}
LL get(LL b, LL x)
{
LL g, i, ret = 0 ;
for (g = 0 ; x > 0 ; x /= b)
w[++g] = x % b;
for (i = g; i >= 1 ; i--)
ret += dp(b, i, 0 , 1 , i == g);
return ret;
}
int main()
{
memset (ans, -1 , sizeof (ans));
scanf ("%I64d" , &q);
while (q--)
{
scanf ("%I64d%I64d%I64d" , &b, &l, &r);
printf ("%I64d\n" , get(b, r) - get(b, l - 1 ));
}
return 0 ;
}
小结:
**此类题目较难。**