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;	
	}
}
*/
posted @ 2019-10-18 21:39  Luckyblock  阅读(102)  评论(0编辑  收藏  举报