132 - The 14th Zhejiang University Programming Contest
A题签到题。
B题打表发现,每个数都最多由三段组成,然后最小的一段不超过100,然后就变成大水题了。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define LL long long
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 20000;
const int INF = 123456789;
map<int, int > mp;
int sum[maxn];
int main()
{
sum[0] = 0;
for(int i = 1; i < maxn; i ++)
{
sum[i] = sum[i - 1] + i;
mp[sum[i]] = i;
}
int n, T = 0, a1, a2, a3;
scanf("%d", &T);
while(T --)
{
scanf("%d", &n);
for(int i = 0; i < 100; i ++)
{
for(int j = 0; sum[i] + sum[j] <= n; j ++)
{
int tmp = sum[i] + sum[j];
if(mp.count(n - tmp))
{
a1 = i, a2 = j, a3 = mp[n-tmp];
goto ed;
}
}
}
ed:;
bool flag = false;
if(a1) printf("%d", a1), flag = true;
if(a2)
{
if(flag) putchar(' ');
printf("%d", a2);
flag = true;
}
if(a3)
{
if(flag) putchar(' ');
printf("%d", a3);
}
puts("");
}
}
C题应该是母函数吧。比赛时TLE了n次没过。。。=.=!!!赛后优化了一下就过了。。。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cstdio>
#include <cmath>
#include <stack>
#include<map>
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define E exp(double(1))
#define eps 1e-7
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
const int maxn = 50500;
char ch[30][30] =
{
"Head", "Shoulder", "Neck", "Torso", "Hand",
"Wrist", "Waist", "Legs", "Feet", "Finger",
"Shield", "Weapon", "Two-Handed"
};
map<string, int> mp;
int fig[maxn];
int eng[2][maxn];
vector<int> d[20], t[20];
void init()
{
for(int i = 0; i < 13; i ++) mp[ch[i]] = i, d[i].clear(), t[i].clear();
for(int i = 0; i < 13; i ++) d[i].push_back(0), t[i].push_back(0);
}
int main()
{
int T, n, m;
scanf("%d", &T);
while(T --)
{
scanf("%d%d", &n, &m);
init();
for(int i = 0; i < n; i ++)
{
char op[20];
int dd, tt;
scanf("%s%d%d", op, &dd, &tt);
int id = mp[op];
d[id].push_back(dd);
t[id].push_back(tt);
}
memset(fig, 0, sizeof(fig));
int sz = d[9].size();
for(int i = 0; i < sz; i ++)
for(int j = i + 1; j < sz; j ++)
{
int tmp = d[9][i] + d[9][j];
tmp = min(tmp, m);
fig[tmp] = max(fig[tmp], t[9][i] + t[9][j]);
}
d[9].clear();t[9].clear();
int mx = 0;
for(int i = m; i >= 0; i --)
{
if(fig[i] && fig[i] > mx)
{
d[9].push_back(i);
t[9].push_back(fig[i]);
mx = fig[i];
}
}
d[9].push_back(0), t[9].push_back(0);
for(int i = 0; i < 2; i ++)
for(int j = 0; j <= m; j ++) eng[i][j] = -1;
int now = 0;
eng[1][0] = 0;
for(int i = 0; i < 10; i ++)
{
for(int j = 0; j <= m; j ++) eng[now][j] = -1;
for(int j = 0; j <= m; j ++) if(eng[now^1][j] != -1)
{
int sz = d[i].size();
for(int k = 0; k < sz; k ++)
{
if(t[i][k] + j >= m)
{
eng[now][m] = max(d[i][k] + eng[now^1][j], eng[now][m]);
}
else
{
int tmp = t[i][k] + j;
eng[now][tmp] = max(d[i][k] + eng[now^1][j], eng[now][tmp]);
}
}
}
now ^= 1;
}
// for(int j = 0; j <= m; j ++) eng[now][j] = -1;
// for(int j = 0; j <= m; j ++) if(eng[now^1][j] != -1)
// {
// int sz = d[9].size();
// for(int k = 0; k < sz; k ++)
// for(int kk = k+1; kk < sz; kk ++) if(k != kk)
// {
// if(t[9][k] + t[9][kk] + j >= m)
// {
// eng[now][m] = max(d[9][k] + d[9][kk] + eng[now^1][j], eng[now][m]);
// }
// else
// {
// int tmp = t[9][k] + j + t[9][kk];
// eng[now][tmp] = max(d[9][k] + d[9][kk] + eng[now^1][j], eng[now][tmp]);
// }
// }
// }
// now ^= 1;
int ans = -2;
for(int j = 0; j <= m; j ++) eng[now][j] = -1;
for(int j = 0; j <= m; j ++) if(eng[now^1][j] != -1)
{
int sz = d[12].size();
for(int k = 0; k < sz; k ++)
{
if(t[12][k] + j >= m)
{
eng[now][m] = max(d[12][k] + eng[now^1][j], eng[now][m]);
}
else
{
int tmp = t[12][k] + j;
eng[now][tmp] = max(d[12][k] + eng[now^1][j], eng[now][tmp]);
}
}
}
ans = max(ans, eng[now][m]);
for(int i = 10; i < 12; i ++)
{
for(int j = 0; j <= m; j ++) eng[now][j] = -1;
for(int j = 0; j <= m; j ++) if(eng[now^1][j] != -1)
{
int sz = d[i].size();
for(int k = 0; k < sz; k ++)
{
if(t[i][k] + j >= m)
{
eng[now][m] = max(d[i][k] + eng[now^1][j], eng[now][m]);
}
else
{
int tmp = t[i][k] + j;
eng[now][tmp] = max(d[i][k] + eng[now^1][j], eng[now][tmp]);
}
}
}
now ^= 1;
}
ans = max(ans, eng[now^1][m]);
printf("%d\n", ans);
}
}
D题水题。
F题可以把递推式写成矩阵乘法,然后用倍增处理从L位置开始到达位置需要乘的矩阵,然后就直接倍增就可以了。。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cstdio>
#include <cmath>
#include <stack>
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define E exp(double(1))
#define eps 1e-7
using namespace std;
#ifdef __int64
typedef __int64 LL;
#else
typedef long long LL;
#endif
const int maxn = 100100;
const LL mod = 1000000007;
struct Maxtr
{
LL m[2][2];
void pt()
{
puts("~~~~~~~~~~~~~~~~~~~");
for(int i = 0; i < 2; i ++)
{
for(int j = 0; j < 2; j ++)
printf("%lld ", m[i][j]);puts("");
}
puts("*******************");
}
}T[maxn][20], pre;
Maxtr Mul(Maxtr a, Maxtr b)
{
Maxtr ret;
for(int i = 0; i < 2; i ++)
{
for(int j = 0; j < 2; j ++)
{
ret.m[i][j] = 0;
for(int k = 0; k < 2; k ++)
{
ret.m[i][j] += a.m[i][k] * b.m[k][j];
}
ret.m[i][j] %= mod;
}
}
return ret;
}
LL A[maxn];
int main()
{
int n, M, t;
scanf("%d", &t);
for(int i = 0; i < 2; i ++)
for(int j = 0; j < 2; j ++)
pre.m[i][j] = (i == j);
while(t --)
{
scanf("%d%d", &n, &M);
for(int i = 1; i <= n; i ++)
{
scanf("%lld", &A[i]);
}
for(int i = 1; i <= n; i ++)
{
T[i][0].m[0][0] = 0;
T[i][0].m[0][1] = A[i];
T[i][0].m[1][0] = 1;
T[i][0].m[1][1] = 1;
}
for(int j = 1; (1 << j) <= n; j ++)
{
for(int i = 1; i + (1 << (j - 1)) <= n; i ++)
{
T[i][j] = Mul(T[i][j - 1], T[i + (1 << (j - 1))][j - 1]);
}
}
for(int i = 0; i < M; i ++)
{
int l, r;LL f1, f2;
scanf("%d%d", &l, &r);
if(l == r)
{
printf("%lld\n", A[l] % mod);
continue;
}
f1 = A[l], f2 = A[l + 1];
int ca = r - l - 1, now = l + 2;
Maxtr mu = pre;
for(int i = 20; i >= 0; i --) if((1 << i) & ca)
{
mu = Mul(mu, T[now][i]);
now += (1 << i);
}
LL ans = f1 * mu.m[0][1] + f2 * mu.m[1][1];
printf("%lld\n", ans % mod);
}
}
}
I题水题。