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
4

1
2 9 3

3
5 4 8

4
3 2 7

5
8 1 6

4

move
1

move
1

change
1 4 100

move
1

4
2

1
3

1
4

【数据范围】

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模拟题解的更多相关文章

  1. HGOI20181029模拟题解

    HGOI20181029模拟题解 /* sxn让我一定要谴责一下出题人和他的数据! */ problem: 给出十进制数a,b,然后令(R)10=(a)10*(b)10,给出c表示一个k进制数(1&l ...

  2. 【 P3952】 时间复杂度 大模拟题解

    题目链接 完全模拟 1.模拟结果 当我们的模拟程序执行结束时,直接执行模拟结果函数,用于比对我们的结果和数据给出的结果. bool yes(char a[],char b[]) { ;i<=;+ ...

  3. HGOI20181031 模拟题解

    sol:第一题就DP?!然后写了O(n^2) dp再考虑优化!!!(尽量部分分带上!!!) 我写了正确的dp然后优化错了,具体的dp方法是考虑到对于右侧到左侧他是没有后效性的 所以定义f[i]为i及以 ...

  4. HGOI20181030 模拟题解

    problem:给定一个序列,问你能不能通过一次交换把他弄成有序 sol: 对于0%的数据,满足数列是一个排列,然后我就打了这档分(自己瞎造的!) 对于100%的数据,显然我们先对数列进行排序然后上下 ...

  5. CSYZDay2模拟题解

    T1.rotate [问题描述] ZYL有N张牌编号分别为1, 2,……,N.他把这N张牌打乱排成一排,然后他要做一次旋转使得旋转后固定点尽可能多.如果第i个位置的牌的编号为i,我们就称之为固定点.旋 ...

  6. 2019-06-03 校内python模拟题解(所有非原题)

    一起来女装吧 本题改编自USACO(USA Computing Olympiad) 1.1节的第一题 (感谢lsy同学对本题题面的贡献) 直接计算就好了 chr:将ASCII码转成字符 ord:字符对 ...

  7. ZOJ Monthly, June 2014 月赛BCDEFGH题题解

    比赛链接:点击打开链接 上来先搞了f.c,,然后发现状态不正确,一下午都是脑洞大开,, 无脑wa,无脑ce...一样的错犯2次.. 硬着头皮搞了几发,最后20分钟码了一下G,不知道为什么把1直接当成不 ...

  8. hdu_5818_Joint Stacks(线段树模拟)

    题目链接:hdu_5818_Joint Stacks 题意: 给你两个栈,多了个合并操作,然后让你模拟 题解: 很容易想到O(1)的单个栈操作,O(n)的合并操作,这样肯定超时,所以我们要将时间复杂度 ...

  9. CSU 1862 The Same Game(模拟)

    The Same Game [题目链接]The Same Game [题目类型]模拟 &题解: 写这种模拟题要看心态啊,还要有足够的时间,必须仔细读题,一定要写一步,就调试一步. 这题我没想到 ...

随机推荐

  1. 绑定IP 绑定设备

    首先引别人的组播测试如下 1. 一个udp client可以同时往多个组播地址发送数据,多个udpclient可以同时往一个组播发数据. 2. 本地udp必须监听组播端口,否则收不到数据.3. 一个u ...

  2. 集训第四周(高效算法设计)H题 (贪心)

    Description   Most financial institutions had become insolvent during financial crisis and went bank ...

  3. MySQL操作示例

    """ MySQL综合练习作业 """ # 1.自行创建测试数据: # 创建数据库 """ create da ...

  4. Light oj-1100 - Again Array Queries,又是这个题,上次那个题用的线段树,这题差点就陷坑里了,简单的抽屉原理加暴力就可以了,真是坑~~

                                                                              1100 - Again Array Queries ...

  5. 洛谷P1257 平面上的最接近点对

    n<=10000个点,求欧几里德距离最小的一对点. 经典分治,把这些点按x排序,分成两半,每边分别算答案,答案是左边的最小,右边的最小,左右组起来的最小三者的最小.发现只有左右组的有点难写. 假 ...

  6. 到达时间自动点击按钮弹出提示并跳转【JavaScript实现】

    原文发布时间为:2008-10-11 -- 来源于本人的百度文章 [由搬家工具导入] 其实我本来是想 做 在线考试的时候 规定时间到达时候自动交卷的,就想到这个例子了。。。。 代码: <html ...

  7. Free Goodies UVA - 12260

    Petra and Jan have just received a box full of free goodies, and want to divide the goodies between ...

  8. 一个1x1px大小Data/Base64数据的gif透明图片

    <img src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNg ...

  9. tornado的http服务器实现

    使用tornado实现的一个简单http服务器:只需要定义自己的处理方法,其他的东西全部交给tornado完成. #coding:utf-8 import tornado.httpserver imp ...

  10. python之SocketServer编程

    编写一个SocketServer需要实现以下步骤 编写一个handler类,继承BaseRequestHandler,重写handle()方法 针对是TCP还是UDP,生成一个server对象 调用s ...