T1 256MB,1Sec

T2 512MB,3Sec

T3 512MB,1Sec

总分:150

试题一

餐馆

题目背景

铜企鹅是企鹅餐馆的老板,他正在计划如何使得自己本年度收益增加。

题目描述

共有n 种食材,一份食材i 需要花\(t_i\) 小时不间断地进行播种,施肥,直至收获。当然,一份食材i 是可以直接卖掉得到\(w_i\) 块钱的。招牌菜共有m 种,一份招牌菜i 需要消耗一定的食材,花\(T_i\) 小时不间断地来烹饪,叫卖,并最终卖出得到\(W_i\) 块钱。整个季度换算下来一共有\(T_{max}\) 小时可供你使用,铜企鹅需要在这期间赚到最多的钱,这样他才有足够多的钱来steam 剁手,或者氪金手游。

输入格式

第一行一个整数T,表示数据组数。

令i 表示为当前数据内行数。

第一行三个整数n; m; \(T_{max}\),含义如题所示。

第二行至第n + 1 行,每行两个整数\(t_{i-1};w_{i-1}\),含义如题所示。

第n + 2 行至第n + m + 1 行,每行两个整数\(T_{i-n-1};W_{i-n-2}\),含义如题所示。

第n + m + 2 行至第n + 2m + 1 行,每行n 个整数,第j 个数\(d_j\) 表示招牌菜i - n - m - 1 需要\(d_j\) 个食材j。

输出格式

对于每组数据,输出一行一个整数,表示你所能赚到的最多的钱。

样例输入

3

1 1 48

2 2000

9 21864

5

4 4 46

17 52

4 36

5 43

16 62

9 31659

1 20431

4 623

1 11961

4 5 3 5

5 4 3 4

3 3 3 3

4 4 5 5

10 0 48

10 41

18 48

2 14

22 65

12 77

7 48

4 85

2 61

24 85

8 34

样例输出

53728

410

1464

数据范围

Subtask 分值 n m T
1 3 1 1 0
2 20 1 1 5
3 10 4 4 5
4 17 2000 0 5
5 50 2000 2000 4

对于100% 的数据,保证\(0 < t_i,T_i \leq T_{max} \leq 5000; 0 \leq w_i,W_i \leq 10^9\),每份招牌菜使用的食材的个数总数不超过\(10^5\)。

分析

考场做法,暨标解

其实招牌菜就是个幌子,转化成食材就可以跑完全背包了。时间复杂度\(O(T_{max} \cdot (n+m))\)

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff; const int MAXN=4e3+7,MAXT=5e3+7; int n,m,maxt;
int t[MAXN],w[MAXN]; ll f[MAXT]; int main()
{
freopen("restaurant.in","r",stdin);
freopen("restaurant.out","w",stdout);
int T;
read(T);
while(T--)
{
memset(t,0,sizeof(t));
memset(w,0,sizeof(w));
memset(f,0,sizeof(f));
read(n);read(m);read(maxt);
for(int i=1;i<=n;++i)
{
read(t[i]);read(w[i]);
}
for(int i=n+1;i<=n+m;++i)
{
read(t[i]);read(w[i]);
}
for(int i=n+1;i<=n+m;++i)
for(int j=1;j<=n;++j)
{
int d;
read(d);
t[i]+=d*t[j];
}
for(int i=1;i<=maxt;++i)
for(int j=1;j<=n+m;++j)
if(i>=t[j])
{
f[i]=max(f[i],f[i-t[j]]+w[j]);
}
printf("%lld\n",f[maxt]);
}
// fclose(stdin);
// fclose(stdout);
return 0;
}

试题二

烯烃

题目背景

银企鹅非常擅长化学。有一天他在试图命名一个巨大的单烯烃分子的时候,想到了一个问题。

题目描述

给你一棵树,一些边有标记,对于每条有标记的边,在树中找到包含这条边的一条最长链,并输出长度。

输入格式

第一行一个整数id 表示测试点的编号。

多组数据,第二行一个整数T 表示数据组数。

对于每组数据,第一行两个整数n;m 表示节点的个数,和被标记的边的个数。

我们规定1 是根,第二行n-1 个整数给出\(2 \sim n\) 父亲的编号,保证\(fa_i < i\)。

第三行m 个整数范围在[2,n] 表示哪个点的父边被标记过。

输出格式

对于每组数据输出一行m 个整数,必须与输入的边顺序一致,给出的是在这条边必选的情况下树中最长链的长度。

样例输入

0

1

10 3

1 2 3 1 4 6 7 3 8

10 7 9

样例输出

8 8 6

数据范围

测试点 n m T 特殊约定
1,2 100 n-1 100
3,4 \(10^5\) 10 100
5 \(10^5\) n-1 100 树是一条链
6 \(10^5\) n-1 100 所有\(fa_i = 1\)
7,8,9,10 \(10^5\) n-1 100

分析

考场40分

40分?被卡常,另外一个数据点的答案错了。

首先直径上的边的最长长度肯定是直径长。

然后非直径上的边的最长长度是最长所在非直径链长度加直径上的最长的一半。

要维护第二个要用直径上一个点重建树,然后用倍增求出最长所在非直径链与直径的交点。

时间复杂度\(O(n \log n+m \log n)\)

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#define rg register
#pragma GCC optimize ("O3")
using namespace std;
template<class T> inline T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff; const int MAXN=1e5+7; struct Edge
{
int nx,to;
}E[MAXN<<1];
int head[MAXN],ecnt; inline void addedge(int x,int y)
{
E[++ecnt].to=y;
E[ecnt].nx=head[x],head[x]=ecnt;
} int n,m;
int fa[MAXN];
int anc[MAXN][20],dep[MAXN],maxd[MAXN]; void dfs1(int x)
{
// cerr<<"dfsing "<<x<<" fa="<<fa[x]<<endl;
dep[x]=dep[fa[x]]+1;
// cerr<<"x="<<x<<" d="<<dep[x]<<endl;
for(rg int i=head[x];i;i=E[i].nx)
{
int y=E[i].to;
// cerr<<" y="<<y<<endl;
if(y==fa[x])
continue;
dfs1(y);
}
} bool onlen[MAXN];
//bool vis[MAXN];
int len; void dfs2(int x,int f)
{
// cerr<<"dfs2 "<<x<<" f=";
dep[x]=maxd[x]=dep[f]+1;
anc[x][0]=f;
for(rg int i=1;i<=19;++i)
anc[x][i]=anc[anc[x][i-1]][i-1];
// vis[x]=1;
// cerr<<anc[x][0]<<endl;
for(rg int i=head[x];i;i=E[i].nx)
{
int z=E[i].to;
if(z==f)
continue;
dfs2(z,x);
maxd[x]=max(maxd[x],maxd[z]);
}
} void dfs3(int x)
{
// cerr<<"dfs3 "<<x<<" f="<<anc[x][0]<<endl;
onlen[x]=1;
int y=0;
for(rg int i=head[x];i;i=E[i].nx)
{
int z=E[i].to;
if(z==anc[x][0])
continue;
if(maxd[z]==maxd[x])
y=z;
}
if(y)
dfs3(y);
} int main()
{
freopen("olefin.in","r",stdin);
freopen("olefin.out","w",stdout);
int id;
read(id);
int T;
read(T);
while(T--)
{
ecnt=0;
memset(head,0,sizeof(head));
dep[0]=-1;
memset(onlen,0,sizeof(onlen));
read(n);read(m);
for(rg int i=2;i<=n;++i)
{
read(fa[i]);
addedge(i,fa[i]);
addedge(fa[i],i);
}
dfs1(1);
int x,dx=0;
for(rg int i=1;i<=n;++i)
if(dep[i]>dx)
{
dx=dep[i];
x=i;
}
dfs2(x,0);
onlen[x]=onlen[0]=1;
dfs3(x);
// cerr<<"x="<<x<<" y="<<y<<endl;
// cerr<<"dx="<<dx<<" dy="<<dy<<endl;
len=maxd[x];
/* for(int i=1;i<=n;++i)
if(onlen[i])
cerr<<"on "<<i<<endl;*/
for(rg int i=1;i<=m;++i)
{
// cerr<<"processing "<<i<<endl;
int q,t;
read(q);
if(dep[fa[q]]>dep[q])
q=fa[q];
t=q;
if(onlen[q])
{
// cerr<<"onlen"<<endl;
printf("%d ",len);
continue;
}
for(rg int j=19;j>=0;--j)
if(!onlen[anc[t][j]])
t=anc[t][j];
t=anc[t][0];
// cout<<"t="<<t<<" onlen="<<onlen[t]<<endl;
int ans=maxd[t]-dep[t];
// cerr<<"ans1="<<ans<<endl;
ans=max(ans,len-ans);
ans+=maxd[q]-dep[t];
printf("%d ",ans);
}
puts("");
}
// fclose(stdin);
// fclose(stdout);
return 0;
}

这个程序加了各种优化之后最慢测试点跑了9秒。

标解

树形dp,要维护换根。

用dp[u]表示这个点所在子树的最大深度。

用fromroot[u]表示从根来的最长链的长度。

然后dp用后序遍历更新,fromroot用父亲更新儿子就行了。

时间复杂度\(O(n+m)\)

#include <bits/stdc++.h>
#define enter putchar('\n')
#define space putchar(' ')
#define pii pair<int,int>
#define fi first
#define se second
#define MAXN 100005
#define pb push_back
#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int N,M,fa[MAXN];
int dp[MAXN],ans[MAXN],fr[MAXN];
struct node {
int to,next;
}E[MAXN * 2];
int head[MAXN],sumE;
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
void dfs1(int u) {
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
dfs1(v);
dp[u] = max(dp[v] + 1,dp[u]);
}
}
void dfs2(int u) {
pii p(0,0);
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
ans[v] = max(dp[v] + 1 + fr[u],ans[v]);
fr[v] = max(fr[v],fr[u] + 1);
if(dp[v] >= dp[p.se]) p.se = v;
if(dp[p.se] >= dp[p.fi]) swap(p.se,p.fi);
}
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != p.fi) {
ans[v] = max(dp[v] + 2 + dp[p.fi],ans[v]);
fr[v] = max(fr[v],dp[p.fi] + 2);
}
else if(p.se) {
ans[p.fi] = max(ans[p.fi],dp[p.fi] + 2 + dp[p.se]);
fr[p.fi] = max(fr[p.fi],dp[p.se] + 2);
}
dfs2(v);
}
}
void Solve() {
memset(head,0,sizeof(head));sumE = 0;
memset(fr,0,sizeof(fr));memset(dp,0,sizeof(dp));memset(ans,0,sizeof(ans));
read(N);read(M);
for(int i = 2 ; i <= N ; ++i) {
read(fa[i]);
add(fa[i],i);
}
dfs1(1);dfs2(1);
int x;
for(int i = 1 ; i <= M ; ++i) {
read(x);out(ans[x]);
if(i == M) enter;
else space;
}
}
int main() {
freopen("olefin.in","r",stdin);
freopen("olefin.out","w",stdout);
int id,T;
read(id);read(T);
while(T--) {
Solve();
}
return 0;
}

试题三

三米诺

题目背景

金企鹅同学非常擅长用\(1 \times 2\) 的多米诺骨牌覆盖棋盘的题。有一天,正在背四六级单词的他忽然想:既然两个格子的积木叫“多米诺(domino)”,那么三个格子的的积木一定叫“三米诺(tromino)”了!用三米诺覆盖棋盘的题怎么做呢?

题目描述

用三米诺覆盖\(3 \times n\) 的矩形棋盘,共多少种方案?三米诺可旋转;两种方案不同当且仅当这两种图案直接覆盖在一起无法重叠。

例如n = 2 时,共3 种方案:

输入格式

一行一个整数\(n(n \leq 10^{40000})\),表示棋盘列数。

输出格式

一行一个整数,表示方案数,对998244353 取模。

样例1 输入

2

样例1 输出

3

样例2 输入

3

样例2 输出

10

样例3 输入

29

样例3 输出

543450786

数据范围

对于10% 的数据,\(n \leq 5\);

对于30% 的数据,\(n \leq 10^6\);

对于40% 的数据,\(n \leq 20001000\);

对于60% 的数据,\(n \leq 10^9\);

对于80% 的数据,\(n \leq 10^{1000}\)

对于100% 的数据,\(n \leq 10^{40000}\)。

分析

考场10分

打表。

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff; int f[6]={0,1,3,10,23,62}; int main()
{
freopen("tromino.in","r",stdin);
freopen("tromino.out","w",stdout);
int n;
read(n);
printf("%d\n",f[n]);
// fclose(stdin);
// fclose(stdout);
return 0;
}

标解

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll; const int tb[9][9] = {
{1, 2, 1, 1, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 1, 0, 0, 0},
{0, 1, 0, 0, 1, 0, 0, 0, 0},
}; const int N = 1000005, P = 998244353;
char s[N];
int n; struct matrix {
ll g[9][9];
matrix(){
memset(g, 0, sizeof(g));
}
matrix operator * (const matrix &b) const {
matrix c;
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
for(int k = 0; k < 9; k++)
c.g[i][j] = (c.g[i][j] + g[i][k] * b.g[k][j]) % P;
return c;
}
} mtx, ans, tmp, pw[10]; int main(){
freopen("tromino.in","r",stdin);freopen("tromino.out","w",stdout);
scanf("%s", s);
n = strlen(s);
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
mtx.g[i][j] = tb[j][i];
for(int i = 0; i < 9; i++)
pw[0].g[i][i] = 1;
for(int i = 1; i <= 9; i++)
pw[i] = pw[i - 1] * mtx;
ans = pw[0];
for(int i = 0; i < n; i++){
tmp = ans = ans * ans;
ans = ans * ans;
ans = ans * ans * tmp * pw[s[i] - '0'];
}
printf("%lld\n", ans.g[0][0]); return 0;
}

test20180907 day1的更多相关文章

  1. NOIp2016 Day1&Day2 解题报告

    Day1 T1 toy 本题考查你会不会编程. //toy //by Cydiater //2016.11.19 #include <iostream> #include <cstd ...

  2. day1

    day1.py ][][: ][: ): : ]['lock'] = 0 json.dump(userlist_message, open(userlist, 'w')) break #输错次数到3次 ...

  3. day1作业--登录入口

    作业概述: 编写一个登录入口,实现如下功能: (1)输入用户名和密码 (2)认证成功后显示欢迎信息 (3)输错三次后锁定 流程图: readme: 1.程序配置文件: 黑名单文件blacklist.t ...

  4. luogu1003铺地毯[noip2011 提高组 Day1 T1]

    题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小到大的顺序平行于 ...

  5. Python学习路程day1

    变量起名: 变量名如果太长,推荐使用下划线来分开,让人看得清晰明白.例:nums_of_alex_girl=19 .或者是驼峰写法,即首字母大写.例:NumOfAlexGf=18 注意:不合法的变量起 ...

  6. 团队项目——站立会议 DAY1

    团队项目--站立会议 DAY1        团队成员介绍(5人):张靖颜.何玥.钟灵毓秀.赵莹.王梓萱        今日(2016/5/6)为站立会议的第一天,一起对团队项目进行讨论,并对每个人的 ...

  7. Day1 login

    使用流程: 1.程序启动后,显示欢迎信息,提示用户输入用户名: 2.判断用户是否存在,不存在则提示重新输入,或者关闭程序:客户存在则提示客户输入密码: 3.判断密码是否正确,如果不正确则提示用户重新输 ...

  8. contesthunter CH Round #64 - MFOI杯水题欢乐赛day1 solve

    http://www.contesthunter.org/contest/CH Round %2364 - MFOI杯水题欢乐赛 day1/Solve Solve CH Round #64 - MFO ...

  9. noip2011提高组day1+day2解题报告

    Day1 T1铺地毯https://www.luogu.org/problem/show?pid=1003 [题目分析] 全部读入以后从最后一个往前找,找到一个矩形的范围覆盖了这个点,那这个矩形就是最 ...

随机推荐

  1. Java EE、Java SE和Java ME

    Java SE=Java Standard EditionJava EE=Java Enterprise EditionJava ME=Java Mobile Edition SE主要用于桌面程序,控 ...

  2. spring boot 日志文件配置(logback-spring.xml)亲测可用!

    问题描述:如何配置springboot项目,通过日志配置,使之输出自定义日志. 详细文章:https://blog.csdn.net/gebitan505/article/details/701421 ...

  3. php json josn_decode()返回的是对像,如何把对像转成数组

    php json josn_decode()返回的是对像,如何把对像转成数组 a.php传值页面,使用 json_encode($array)对数组进行加密码. b.php页面在接收a.php传过来的 ...

  4. 多个 CancellationTokenSource 复合(组合) 或 C# 使用 CancellationTokenSource 终止线程

    https://www.cnblogs.com/luohengstudy/p/5623451.html https://www.cnblogs.com/wlzhang/p/4604471.html

  5. English trip WeekEnd-Lesson 2018.11.10

    本周末上了三节课,做个小结吧\(^o^)/~: [102] 新概念一早读 - 27 - 28        Teacher: March Mrs. Smith's living room is lar ...

  6. 20170503xlVBA房地产数据分类连接

    Sub NextSeven_CodeFrame4() Application.ScreenUpdating = False Application.DisplayAlerts = False Appl ...

  7. hdu 6396 Swordsman (技巧)

    大意: n个怪, m种能力值, 当自己所有能力值不低于某只怪时可以杀死它, 并获得它的所有能力, 求最大杀几只 将每只怪拆成$m$个, 排下序贪心即可, 复杂度$O(nm)$, 原题极其卡时间, 我的 ...

  8. 『cs231n』作业3问题4选讲_图像梯度应用强化

    [注],本节(上节也是)的model是一个已经训练完成的CNN分类网络. 随机数图片向前传播后对目标类优化,反向优化图片本体 def create_class_visualization(target ...

  9. 从mysql数据库删除重复记录只保留其中一条

    这两天做了一个调用第三方接口的小程序,因为是实时更新数据,所以请求接口的频率就很高,这样有时会出现往数据库插入重复的数据,对数据库造成压力也不方便管理,因为要通过原生sql语句,解决数据库的去重问题. ...

  10. throw new OAException执行了,却没有正常抛出异常!

    try { if ("E".equals(returnStatus)) { throw new OAException(returnMessage, OAException.ERR ...