2019.10.18 题解报告
2019.10.18 题解报告
AK开心
答题情况:
- 总成绩 : 300, 排名:1(名次) / 35(总人数)
- T1 : 100 T2 : 100 T3 : 100
各题目分析:
-
题目1:
预估成绩 : 100 实际成绩 :100 考试用时 : 8:00 ~ 8 : 40数据范围奇小 , 不需要考虑什么高深算法, 直接 多次KMP匹配即可
对于数据的把握和时间复杂度的估计是成败的关键。
-
题目2:
预估成绩 : 100 实际成绩 :100 考试用时 : 8:50 ~ 9:20先直接打的暴力BFS, 发现过不了样例 ,
发现 每个位置存在 最优性的性质 , 于是进行了 记忆化要善于 分析题意性质 , 以得到合适的优化方式
-
题目3:
预估成绩 : 100 实际成绩 : 100 考试用时 : 9:40 ~ 10:50暴搜打表 , 找递推规律即可
高精是最恶心的
题目解析:
T1:
对于 每一个被匹配串,
枚举 m个匹配串 使用KMP算法对其进行匹配
每匹配成功一次 , 就计算出其贡献 , 并累加
复杂度O(n^3) , 稳过 n<=200
T2:
记忆化广搜即可
每次 枚举可以转移的位置
当 经过路径权值和 权值和 > 到达位置和时转移
由于广搜的 性质 , 不会受到 搜索层数的影响
T3:
By:Luckyblock ×
By:ZlycerQan √
首先感谢zlq提供的强大高精
sto zlq orz
打表找规律:
1 0
2 1
3 2 = (1 + 0) * 2
4 9 = (1 + 2) * 3
5 44 = (9 + 2) * 4
6 265 = (44 + 9)* 5
7 1854 = (265 + 44) * 6
8 14833 = ...
9 133496
10 1334961
11 14684570
12 176214841
可以得到 i >=3时的 递推式f[i] = (f[i-1] + f[i-2]) * (i-1)
高精是最恶心的
代码实现:
T1:
- 考场代码(正解):
#include<cstdio>
#include<cstring>
#include<ctype.h>
#define ll long long
const int MARX = 210;
//=============================================================
int n,m, i,j,k,lth1,lth2, a[MARX],next[MARX];
char t[MARX][MARX], s[MARX];
ll ans;
//=============================================================
inline int read()
{
int s=1, w=0; char ch=getchar();
for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
for(; isdigit(ch);ch=getchar()) w = w*10+ch-'0';
return s*w;
}
void Get_next()
{
int pos1 = 0, pos2 = -1;
next[0] = -1;
while(pos1 < lth2)
if(pos2 == -1 || t[j][pos1] == t[j][pos2])
{
pos1 ++, pos2 ++;
next[pos1] = pos2;
}
else pos2 = next[pos2];
}
void Kmp()
{
int pos1 = 0, pos2 = 0;
while(pos1 < lth1)
{
if(pos2 == -1 || s[pos1] == t[j][pos2]) pos1++, pos2++;
else pos2 = next[pos2];
if(pos2 == lth2) ans += (long long)(pos1 - lth2 + 1)* (long long)a[j], pos2 = next[pos2];
}
}
//=============================================================
signed main()
{
freopen("dream.in","r",stdin);
freopen("dream.out","w",stdout);
n = read(), m = read();
for(i = 1; i <= m; i ++) scanf("%s",t[i]);
for(i = 1; i <= m; i ++) a[i] = read();
for(i = 1; i <= n; i ++)
{
scanf("%s",s); lth1 = strlen(s);
for(j = 1; j <= m; j ++)
{
lth2 = strlen(t[j]);
Get_next();
Kmp();
}
}
printf("%lld",ans);
}
T2:
- 考场代码(正解):
#include<cstdio>
#include<queue>
#include<ctype.h>
#define max(a,b) (a>b?a:b)
#define int long long
const int MARX = 310;
const int ex[5] = {0, 0, 1, -1};
const int ey[5] = {1, -1, 0, 0};
//=============================================================
int n,m,sx,sy,ans;
int a[MARX][MARX], marx[MARX][MARX];
//=============================================================
inline int read()
{
int s=1, w=0; char ch=getchar();
for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
for(; isdigit(ch);ch=getchar()) w = w*10+ch-'0';
return s*w;
}
void Bfs()
{
std::queue <int> x,y,step,sum;
x.push(sx), y.push(sy), step.push(0), sum.push(0);
for(; !x.empty(); )
{
int tx = x.front(), ty = y.front(), ts = step.front(), tsum = sum.front();
x.pop(), y.pop(), step.pop(), sum.pop();
for(int i = 0; i < 4; i ++)
if(tx + ex[i] > 0 && tx + ex[i] <= n)
if(ty + ey[i] > 0 && ty + ey[i] <= m)
if(a[tx + ex[i]][ty + ey[i]] != -1)
if(tsum + a[tx + ex[i]][ty + ey[i]] > marx[tx + ex[i]][ty + ey[i]])
{
marx[tx + ex[i]][ty + ey[i]] = tsum + a[tx + ex[i]][ty + ey[i]];
if(ts == 22)
{
ans = max(ans, tsum + a[tx + ex[i]][ty + ey[i]]);
continue;
}
x.push(tx + ex[i]);
y.push(ty + ey[i]);
step.push(ts + 1);
sum.push(tsum + a[tx + ex[i]][ty + ey[i]]);
// printf("%lld",step.front());
}
}
}
//=============================================================
signed main()
{
freopen("corner.in","r",stdin);
freopen("corner.out","w",stdout);
m = read(), n = read();
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
{
a[i][j] = read();
if(a[i][j] == 0) sx = i, sy = j;
}
Bfs();
printf("%lld",ans);
}
T3:
- 考场代码(正解) :
#include<cstdio>
#include<iostream>
#include<vector>
#include<iomanip>
#include<cassert>
#include<algorithm>
#include<cstring>
#define rg register
#define LL long long
const int MARX = 1010;
const int Big_B = 10; const int Big_L = 1;
inline int intcmp_ (int a, int b) { if (a > b) return 1; return a < b ? -1 : 0; }
struct Int
{
inline int max(int a, int b) {return a > b ? a : b;}
inline int min(int a, int b) {return a < b ? a : b;}
std :: vector <int> c; Int () {}
Int (int x) { for (; x > 0; c.push_back (x % Big_B), x /= Big_B); }
Int (LL x) { for (; x > 0; c.push_back (x % Big_B), x /= Big_B); }
inline void CrZ () { for (; !c.empty () && c.back () == 0; c.pop_back ()); }
inline Int &operator += (const Int &rhs)
{
c.resize (max (c.size (), rhs.c.size ())); rg int i, t = 0, S;
for (i = 0, S = rhs.c.size (); i < S; ++ i)
c[i] += rhs.c[i] + t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
c[i] += t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
if (t) c.push_back (t); return *this;
}
inline Int &operator *= (const Int &rhs)
{
rg int na = c.size (), i, j, S, ai;
c.resize (na + rhs.c.size ()); LL t;
for (i = na - 1; i >= 0; -- i)
{
ai = c[i], t = 0, c[i] = 0;
for (j = 0, S = rhs.c.size (); j < S; ++ j)
{
t += c[i + j] + (LL) ai * rhs.c[j];
c[i + j] = t % Big_B, t /= Big_B;
}
for (j = rhs.c.size (), S = c.size (); t != 0 && i + j < S; ++ j)
t += c[i + j], c[i + j] = t % Big_B, t /= Big_B;
assert (t == 0);
}
CrZ (); return *this;
}
friend inline Int operator + (const Int &lhs, const Int &rhs)
{ Int res = lhs; return res += rhs; }
friend inline Int operator * (const Int &lhs, const Int &rhs)
{ Int res = lhs; return res *= rhs; }
friend inline std :: ostream &operator << (std :: ostream &out, const Int &rhs)
{
if (rhs.c.size () == 0) out << "0";
else
{
out << rhs.c.back ();
for (rg int i = rhs.c.size () - 2; i >= 0; -- i)
out << std :: setfill ('0') << std :: setw (Big_L) << rhs.c[i];
}
return out;
}
};
//=============================================================
LL n;
Int f[MARX];
//=============================================================
inline LL read()
{
LL s = 1, w=0; char ch=getchar();
for(; !isdigit(ch); ch=getchar()) if(ch=='-') s =-1;
for(; isdigit(ch); ch=getchar()) w = w*10+ch-'0';
return s*w;
}
//=============================================================
signed main()
{
freopen("keke.in","r",stdin);
freopen("keke.out","w",stdout);
n = read();
f[1] = 0, f[2] = 1;
if(n <= 2) { std::cout << f[n]; return 0; }
for(rg int i = 3; i <= n; i ++) f[i] = (f[i - 1] + f[i - 2]) * (i - 1);
std::cout << f[n];
}
/*
#include<cstdio>
#include<ctype.h>
#define int long long
const int MARX = 1010;
//=============================================================
int n,ans,f[MARX];
int map[MARX][MARX], use[MARX];
//=============================================================
inline int read()
{
int s=1, w=0; char ch=getchar();
for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
for(; isdigit(ch);ch=getchar()) w = w*10+ch-'0';
return s*w;
}
void dfs(int now)
{
if(now == n + 1)
{
// for(int i = 1; i <= n ; putchar('\n'),i ++)
// for(int j = 1; j <= n ; j++)
// printf("%d ",map[i][j]);
// putchar('\n');
ans ++;
return ;
}
for(int i = 1; i <= n; i ++)
if(i != now && use[i] == 0)
{
use[i] = 1, map[now][i] = 2;
dfs(now+1);
use[i] = 0, map[now][i] = 0;;
}
}
//=============================================================
signed main()
{
int last = 0;
for(int i = 1; i <= 100; i ++) map[i][i] = 1;
for(n = 1; n <= 12; n ++)
{
dfs(1);
f[n] = ans;
printf("%lld %lld\n",ans,(f[n-2] + f[n-1])*(n-1));
last = ans, ans = 0;
}
}
*/