CSYZDay1模拟题解
T1.game
【问题描述】
LZK发明一个矩阵游戏,大家一起来玩玩吧,有一个N行M列的矩阵。第一行的数字是1,2,…M,第二行的数字是M+1,M+2…2*M,以此类推,第N行的数字是(N-1)*M+1,(N-1)*M+2…N*M。
例如,N=3,M=4的矩阵是这样的:
-
1
2
3
4
5
6
7
8
9
10
11
12
对于身为智慧之神的LZK来说,这个矩阵过于无趣.于是他决定改造这个矩阵,改造会进行K次,每次改造会将矩阵的某一行或某一列乘上一个数字,你的任务是计算最终这个矩阵内所有数字的和,输出答案对109+7取模。
【输入】
第一行包含三个正整数N、M、K,表示矩阵的大小与改造次数。接下来的行,每行会是如下两种形式之一:
R X Y,表示将矩阵的第X(1 ≤ X ≤ N)行变为原来的Y(0 ≤ Y ≤109)倍.
S X Y,表示将矩阵的第X(1 ≤ X ≤ M)列变为原来的Y(0 ≤ Y ≤)倍.
【输出】
输出一行一个整数,表示最终矩阵内所有元素的和对109+7取模的结果。
【数据范围】
40%的数据满足:1≤N,M≤1000;
80%的数据满足:1≤N,M≤1000000,1 ≤ K ≤1000;
100%的数据满足:1≤N,M≤1000000,1 ≤ K ≤100000。、
个人觉得T1还是比较简单的,因为这个矩阵最后的和与乘法操作的先后顺序没有关系,所以我们可以先把所有行的操作乘完,记录每行被乘的数取模之后的结果。之后选择把第一列的所有数加起来,后面每列与之相差的值就是每行被乘的倍数之和。这样的话线性相加之后每次再乘以这一列被乘的情况就可以啦。
看一下代码。千万要注意在linux下有字符读入的不要使用单个的getchar,否则在读取的时候会出错,可以选择使用cin,scanf或者多个getchar进行读入。
(这题在Linux下评测的话我原来代码会爆零,但是windows下是可以过的)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<set>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = ;
const int N = ;
const ll mod = 1e9+; ll read()
{
ll ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
} struct ask
{
ll pos,val;
}r[M],s[M];
ll n,m,k,tot1,tot2,cur,ans,sum;
ll po[N],ro[N]; int main()
{
//freopen("game.in","r",stdin);
//freopen("game.out","w",stdout);
n = read(),m = read(),k = read();
rep(i,,k)
{
char c;
cin >> c;
if(c == 'R') r[++tot1].pos = read(),r[tot1].val = read();
else if(c == 'S')s[++tot2].pos = read(),s[tot2].val = read();
}
rep(i,,n) po[i] = ;rep(i,,m) ro[i] = ;
rep(i,,tot1) po[r[i].pos] *= r[i].val,po[r[i].pos] %= mod;
rep(i,,n)
{
ll p = + (i-) * m; p %= mod;
cur += p * po[i],cur %= mod;
sum += po[i];
if(sum >= mod) sum -= mod;
}
rep(i,,tot2) ro[s[i].pos] *= s[i].val,ro[s[i].pos] %= mod;
rep(i,,m)
{
ans += cur * ro[i],ans %= mod;
cur += sum;
if(cur >= mod) cur -= mod;
}
printf("%lld\n",ans);
return ;
}
T2.jump
【问题描述】
跳房子,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一。
跳房子是在N个格子上进行的,CYJ对游戏进行了改进,该成了跳棋盘,改进后的游戏是在一个N行M列的棋盘上进行,并规定从第一行往上可以走到最后一行,第一列往左可以走到最后一列,反之亦然。每个格子上有一个数字。
在这个棋盘左上角(1,1)放置着一枚棋子。每次棋子会走到右、右上和右下三个方向格子中对应上数字最大一个。即任意时刻棋子都只有一种走法,不存在多个格子同时满足条件。
现在有两种操作:
move
k 将棋子前进k步。
change
a b e 将第a行第b列格子上的数字修改为e。
请对于每一个move操作输出棋子移动完毕后所处的位置。
【输入】
第一行包含两个正整数N,M(3<=N,M<=2000),表示棋盘的大小。
接下来N行,每行M个整数,依次表示每个格子中的数字a[i,j](1<=
a[i,j]<=109)。
接下来一行包含一个正整数Q(1<=Q<=5000),表示操作次数。
接下来m行,每行一个操作,其中1<=a<=N,1<=b<=M,1<=k,e<=109。
【输出】
对于每个move操作,输出一行两个正整数x,y,即棋子所处的行号和列号。
【输入输出样例】
jump.in |
jump.out |
4 1 3 4 5 4 move move change move |
4 1 1 |
【数据范围】
10%的数据满足:3<=
N,M
<=50,Q<=5000,k<=10;
20%的数据满足:3<=
N,M
<=200,Q<=5000,k<=5000;
另有20%的数据满足:3<=
N,M
<=200,Q<=5000,k<=109;
100%的数据满足:3<=
N,M
<=2000,Q<=5000,e,k<=109;
这题当时想到了暴力的40分不过由于没有时间给写跪了。因为n×m内必出循环节(踩到一个走过的格子即进入循环节)
至于100分做法怎么做呢?正解的做法我看不大懂……所以使用了学姐的线段树维护置换的方法。我们记录对于每一列,在每一行其向下一列会走到哪。这样的话每一列都建立了一个置换,之后我们只要把他们全部乘起来就行。在行走的时候,如果步数够得话就直接用置换跳着走(每次走m列),否则一步一步走就可以。
至于修改操作,我们只需要修改这个点的左边,左上,左下三个点,之后直接在线段树内重新维护置换即可。
或许很难懂……看一下子恒dalao的代码。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#include<set>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = ;
const int N = ; int read()
{
int ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
} int n,m,f[N][N];
char s[]; struct node
{
int g[N];
node()
{
rep(i,,n) g[i] = i;
}
node operator * (const node &b)const
{
node c;
rep(i,,n) c.g[i] = b.g[g[i]];
return c;
}
}nxt[N],t[N<<]; node qpow(node k,int b)
{
node res;
while(b)
{
if(b & ) res = res * k;
k = k * k;
b >>= ;
}
return res;
} int pos(int x,bool flag)//pos函数用于确定取模之后的实际位置
{
if(x == (flag ? m+ : n+)) return ;
if(!x) return flag ? m : n;
return x;
} void change(int x,int y)
{
int maxn = ;
x = pos(x,),y = pos(y,);
rep(k,-,)
{
int kx = pos(k+x,),ky = pos(y+,);
if(maxn < f[kx][ky]) maxn = f[kx][ky],nxt[y].g[x] = kx;
}
} void build(int p,int l,int r)
{
if(l == r)
{
t[p] = nxt[l];
return;
}
int mid = (l+r) >> ;
build(p<<,l,mid);
build(p<<|,mid+,r);
t[p] = t[p<<] * t[p<<|];
} void modify(int p,int l,int r,int v)
{
if(l == r)
{
t[p] = nxt[v];
return;
}
int mid = (l+r) >> ;
if(v <= mid) modify(p<<,l,mid,v);
else modify(p<<|,mid+,r,v);
t[p] = t[p<<] * t[p<<|];
}
void move(int &x,int &y,int k)
{
while(k--) x = nxt[y].g[x],y = pos(y+,);
} int main()
{
n = read(),m = read();
rep(i,,n)
rep(j,,m) f[i][j] = read();
rep(i,,n)
rep(j,,m) change(i,j);
build(,,m);
int q = read(),px = ,py = ;
while(q--)
{
scanf("%s",s);
if(s[] == 'm')
{
int k = read(),len = min(k,m - py + );
move(px,py,len),k -= len;
if(k) px = qpow(t[],k/m).g[px],k %= m,move(px,py,k);
printf("%d %d\n",px,py);
}
else
{
int a = read(),b = read(),c = read();
f[a][b] = c;
change(a-,b-),change(a,b-),change(a+,b-);
modify(,,m,pos(b-,));
}
}
return ;
}
T3.sequence
这题确实不会做了……考试的时候线段树无限暴力52pts。
正解也看不大懂……直接放出暴力代码吧。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<set>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = ;
const int INF = 1e9+; int read()
{
int ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
} struct seg
{
int v,minx,maxx;
}t[M<<]; int n,m,a[M],al,ar,pos[][],tot[M]; void build(int p,int l,int r)
{
if(l == r)
{
t[p].minx = t[p].maxx = a[l];
return;
}
int mid = (l+r) >> ;
build(p<<,l,mid);
build(p<<|,mid+,r);
t[p].minx = min(t[p<<].minx,t[p<<|].minx);
t[p].maxx = max(t[p<<].maxx,t[p<<|].maxx);
} int query(int p,int l,int r,int kl,int kr,bool flag)
{
if(l == kl && r == kr) return flag? t[p].minx : t[p].maxx;
int mid = (l+r) >> ;
if(kr <= mid) return query(p<<,l,mid,kl,kr,flag);
else if(kl > mid) return query(p<<|,mid+,r,kl,kr,flag);
else
{
if(flag) return min(query(p<<,l,mid,kl,mid,flag),query(p<<|,mid+,r,mid+,kr,flag));
else return max(query(p<<,l,mid,kl,mid,flag),query(p<<|,mid+,r,mid+,kr,flag));
}
} void init()
{
rep(i,,n)
{
rep(j,i+,n)
{
int k1 = query(,,n,i,j,),k2 = query(,,n,i,j,);
if(k2-k1+ == j-i+) pos[i][++tot[i]] = j;
}
}
} void solve(int l,int r)
{
int cur = INF,pos1,pos2;
per(i,l,)
{
int k = lower_bound(pos[i]+,pos[i]++tot[i],r) - pos[i];
if(k == tot[i]+) continue;
if(pos[i][k]-i+ < cur) cur = pos[i][k]-l+,pos1 = i,pos2 = pos[i][k];
}
printf("%d %d\n",pos1,pos2);
}
int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
n = read(); rep(i,,n) a[i] = read();
build(,,n);
init();
m = read();
rep(i,,m)
{
al = read(),ar = read();
solve(al,ar);
}
return ;
}
这么长时间过去还是没有理解这题咋做……太弱了orz。
算是把坑填一下。
CSYZDay1模拟题解的更多相关文章
- HGOI20181029模拟题解
HGOI20181029模拟题解 /* sxn让我一定要谴责一下出题人和他的数据! */ problem: 给出十进制数a,b,然后令(R)10=(a)10*(b)10,给出c表示一个k进制数(1&l ...
- 【 P3952】 时间复杂度 大模拟题解
题目链接 完全模拟 1.模拟结果 当我们的模拟程序执行结束时,直接执行模拟结果函数,用于比对我们的结果和数据给出的结果. bool yes(char a[],char b[]) { ;i<=;+ ...
- HGOI20181031 模拟题解
sol:第一题就DP?!然后写了O(n^2) dp再考虑优化!!!(尽量部分分带上!!!) 我写了正确的dp然后优化错了,具体的dp方法是考虑到对于右侧到左侧他是没有后效性的 所以定义f[i]为i及以 ...
- HGOI20181030 模拟题解
problem:给定一个序列,问你能不能通过一次交换把他弄成有序 sol: 对于0%的数据,满足数列是一个排列,然后我就打了这档分(自己瞎造的!) 对于100%的数据,显然我们先对数列进行排序然后上下 ...
- CSYZDay2模拟题解
T1.rotate [问题描述] ZYL有N张牌编号分别为1, 2,……,N.他把这N张牌打乱排成一排,然后他要做一次旋转使得旋转后固定点尽可能多.如果第i个位置的牌的编号为i,我们就称之为固定点.旋 ...
- 2019-06-03 校内python模拟题解(所有非原题)
一起来女装吧 本题改编自USACO(USA Computing Olympiad) 1.1节的第一题 (感谢lsy同学对本题题面的贡献) 直接计算就好了 chr:将ASCII码转成字符 ord:字符对 ...
- ZOJ Monthly, June 2014 月赛BCDEFGH题题解
比赛链接:点击打开链接 上来先搞了f.c,,然后发现状态不正确,一下午都是脑洞大开,, 无脑wa,无脑ce...一样的错犯2次.. 硬着头皮搞了几发,最后20分钟码了一下G,不知道为什么把1直接当成不 ...
- hdu_5818_Joint Stacks(线段树模拟)
题目链接:hdu_5818_Joint Stacks 题意: 给你两个栈,多了个合并操作,然后让你模拟 题解: 很容易想到O(1)的单个栈操作,O(n)的合并操作,这样肯定超时,所以我们要将时间复杂度 ...
- CSU 1862 The Same Game(模拟)
The Same Game [题目链接]The Same Game [题目类型]模拟 &题解: 写这种模拟题要看心态啊,还要有足够的时间,必须仔细读题,一定要写一步,就调试一步. 这题我没想到 ...
随机推荐
- 201621123079《Java程序设计》第1周学习总结
第1周-Java基本概念 1.本周学习总结 第一次上课接触java,了解了java的由来和历史,还有JCP,JSP的概念,并学会如何建立一个java文件和运行过程.感觉java比之前学习的数据结构更高 ...
- Python之禅 吾心笃定
自从3月19日到现在已经学习python 19天了,博客园也注册8天了.之所以一直没有急着分享学习中的知识是因为我觉得学习一道应该从心开始,所以第一篇随笔不应该说python的知识,而应该说学习心态和 ...
- 21Spring重用切点表达式
直接看代码: package com.cn.spring.aop.impl; //加减乘除的接口类 public interface ArithmeticCalculator { int add(in ...
- C++ 类 直接定义对象与new对象的区别
new创建类对象与直接定义的区别 new创建对象的特点 new创建类对象需要指针接收,一处初始化,多处使用 new创建类对象使用完需delete销毁 new创建对象直接使用堆空间,而局部不用new定义 ...
- HTML文件中css样式的引用
1.1.直接在div中使用css样式制作div+css网页 如: <div style="font-size:14px; color:#FF0000;">内容</ ...
- 完美解决了span的宽度设置
下 面代码的CSS定义完美解决了span的宽度设置问题.由于浏览器通常对不支持的CSS属性采取忽略处理的态度,所以最好将display:inline -block行写在后面,这样在Firefox里面, ...
- Big String(poj 2887)
题意: 给你一个不超过1e6的字符串,和不超过2000次的操作 操作分为两种: 1.将一个字符插入到某个位置的前面 2.询问当前位置的字符 /* 块状链表模板水题(我的智商也就能做这种题了). 观察题 ...
- msp430入门编程07
msp430中C语言的函数及实现07 msp430中C语言操作端口I/O10 msp430中C语言的模块化头文件及实现11 msp430中C语言的模块化头文件及库文件12 msp430入门学习 msp ...
- 利用mysql分析小规模数据
1 获取数据 示例:(/home/work/data/1.data) 123457,chenli,70 123458,liuyang,71 2 create table CREATE TABLE sc ...
- 类(Class)
类 · 目的 面向对象的最主要目的是提高程序的重复使用性. · 包括 属性(attribute).方法(method) · 示例 class Bird(object): have_feather = ...