8.5 NOIP模拟测试13 矩阵游戏+跳房子+优美序列
T1矩阵游戏
数学题。首先这一列这一行先乘还是后乘对最后答案没有影响。a[i][j]表示矩阵中原始的值,h[i]表示i行的累乘,l[i]表示i列的累乘。易得ans=Σa[i][j]*h[i]*l[i]
化简:
ans= Σa[i][j]*h[i]*l[j]=Σh[i]*Σa[i][j]*l[j]
a[i][j]为矩阵的初始值,公差为1的等差数列
以j==3为例 Σa[i][j]*l[j]=a[i][1]*l[1]+a[i][2]*l[2]+a[i][3]*l[3]
=a[i][1]*l[1]+(a[i][1]+1)*l[2]+(a[i][1]+2)*l[3]
=a[i][1]*l[1]+a[i][1]*l[2]+a[i][1]*l[3]+0*l[1]+1*l[2]+2*l[3]
=a[i][1]*(l[1]+l[2]+l[3])+0*l[1]+1*l[2]+2*l[3]
设sum=(l[1]+l[2]+l[3])。Σa[i][j]*l[j]=a[i][1]*sum+0*l[1]+1*l[2]+2*l[3]
a[i][1]=(i-1)*m+1 --> Σa[i][j]*l[j]=((i-1)*m+1)*sum+0*l[1]+1*l[2]+2*l[3]=(i-1)*m*sum+0*l[1]+1*l[2]+2*l[3]+sum
把sum回带 得Σa[i][j]*l[j]=(i-1)*m*sum+1*l[1]+2*l[2]+3*l[3]
设sumlj=1*l[1]+2*l[2]+3*l[3]...
Σa[i][j]*l[j]=(i-1)*m*sum+sunlj
综上,ans=Σh[i]*((i-1)*m*sum+sumlj)
#include<iostream>
#include<cstdio>
#define mod 1000000007
#define ll long long
using namespace std;
ll n,m,k,ans,h[],l[],sumlj,suml;
ll read()
{
register ll aa=,bb=;register char cc=getchar();
while(cc>''||cc<''){if(cc=='-') bb=-;cc=getchar();}
while(cc<=''&&cc>=''){aa=aa*+cc-'';cc=getchar();}
return aa*bb;
}
int main()
{
n=read(),m=read(),k=read();
for(register ll i=;i<=n;i++) h[i]=;
for(register ll i=;i<=m;i++) l[i]=;
register char ch[];register ll x,y;
for(register ll i=;i<=k;i++){
scanf("%s",ch);
x=read();y=read();
if(ch[]=='R') h[x]=h[x]*y%mod;
else l[x]=l[x]*y%mod;
}
for(int i=;i<=m;i++) suml=(suml+l[i])%mod,sumlj=(sumlj+l[i]*i%mod)%mod;
for(int i=;i<=n;i++) ans=(ans+((i-)*m%mod*suml%mod+sumlj)%mod*h[i]%mod)%mod;
printf("%lld\n",ans);
return ;
}
矩阵游戏
T2 跳房子
正解是找循环节,每次跳循环节(码量挺大),在我调了一天也没调出来后我就放弃了。
另一种解法是用线段树维护。
把每一列当作一个节点,每个节点(列)里维护这一列的每一行跳一下会跳到哪,上面的区间里维护从l列的某一行到r+1列哪一行,对于每一次询问,区间查询找到跑一圈的情况,用类似快速幂的东西让他跑k/m圈,剩下的区间查询。这个过程中我们其实已经把从当前列的任意位置开跑的情况都已经处理出来了,只需要查询对应行即可。
change操作只会影响上一列的三个点,但由于第一行和最后一行的情况不好处理,我们可以暴力把这一整列都改了,反正没T。。。线段树单点修改就可以了。
需要注意的是那个类似于初始矩阵的东西,他的含义是从这一行跳会回到这一行,所以c[i]=i 。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,Q,x,y,a[][],jump[],huan,hlen,vis[],bx,by,xa,ya;
char ch[];
struct node
{
int l,r,c[];
}t[];
struct nede
{
int c[];
void init(){for(int i=;i<=n;i++) c[i]=i;}
}ans;
void bl()
{
if(by==m) by=;
else by++;
if(bx==){
if(a[bx][by]>a[bx+][by]&&a[bx][by]>a[n][by]) bx=bx;
else if(a[bx+][by]>a[bx][by]&&a[bx+][by]>a[n][by]) bx=bx+;
else if(a[n][by]>a[bx][by]&&a[n][by]>a[bx+][by]) bx=n;
}
else if(bx==n){
if(a[bx][by]>a[bx-][by]&&a[bx][by]>a[][by]) bx=bx;
else if(a[bx-][by]>a[bx][by]&&a[bx-][by]>a[][by]) bx=bx-;
else if(a[][by]>a[bx][by]&&a[][by]>a[bx-][by]) bx=;
}
else{
if(a[bx][by]>a[bx+][by]&&a[bx][by]>a[bx-][by]) bx=bx;
else if(a[bx+][by]>a[bx][by]&&a[bx+][by]>a[bx-][by]) bx=bx+;
else if(a[bx-][by]>a[bx][by]&&a[bx-][by]>a[bx+][by]) bx=bx-;
}
}
void update(int x)
{
for(int i=;i<=n;i++) t[x].c[i]=t[x*+].c[t[x*].c[i]];
}
void build(int x,int l,int r)
{
t[x].l=l;t[x].r=r;
if(l==r){
for(int i=;i<=n;i++){
bx=i;by=l;
bl();
t[x].c[i]=bx;
}
return;
}
int mid=(l+r)>>;
build(x*,l,mid);
build(x*+,mid+,r);
update(x);
}
void mul(nede a,node b)
{
for(int i=;i<=n;i++) ans.c[i]=b.c[a.c[i]];
}
void query(int x,int l,int r)
{
if(l<=t[x].l&&r>=t[x].r){
mul(ans,t[x]);
return;
}
int mid=(t[x].l+t[x].r)>>;
if(l<=mid) query(x*,l,r);
if(r>mid) query(x*+,l,r);
}
void change(int x,int pos)
{
if(t[x].l==t[x].r&&t[x].l==pos){
for(int i=;i<=n;i++){
bx=i;by=pos;
bl();
t[x].c[i]=bx;
}
return;
}
int mid=(t[x].l+t[x].r)>>;
if(pos<=mid) change(x*,pos);
else change(x*+,pos);
update(x);
}
nede mult(nede a,nede b)
{
nede as;as.init();
for(int i=;i<=n;i++) as.c[i]=b.c[a.c[i]];
return as;
}
nede qpow(nede x,int p)
{
nede as;as.init();
while(p){
if(p&) as=mult(as,x);
x=mult(x,x);
p>>=;
}
return as;
}
int main()
{
// freopen("jump1.in","r",stdin);
// freopen("2.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&a[i][j]);
build(,,m);
scanf("%d",&Q);int xx,yy,zz;
xa=;ya=;
while(Q--){
scanf("%s",ch);
if(ch[]=='m'){
scanf("%d",&xx);
ans.init();
query(,ya,m);
if(ya!=) query(,,ya-);
ans=qpow(ans,xx/m);
int jp=xx%m;
if(jp){
if(ya+jp-<=m) query(,ya,ya+jp-);
else query(,ya,m),query(,,ya+jp-m-);
}
xa=ans.c[xa];ya=(ya+xx-)%m+;
printf("%d %d\n",xa,ya);
}
else{
scanf("%d%d%d",&xx,&yy,&zz);
a[xx][yy]=zz;
if(yy==) change(,m);
else change(,yy-);
}
}
return ;
}
跳房子
T3 优美序列
1.两个好区间的交集也是好区间,所以一个区间向右找到的第一个好区间的右端点就是这个询问区间答案的右端点。
2.一个[l,r]的好区间里,差的绝对值为1的二元组有r-l个。因为把这个区间排序,他肯定是连续的。所以这个可以转化为l+num(二元组)=r,可以当做我们判定一个区间是否为好区间的依据。前边的都已经处理好了,那么当前点i只可能与a[i]+1或a[i]-1构成二元组。包含pos的区间都可以得到1的贡献,所以[1,pos]的区间都可以+1。
离线处理,把所有询问按右边界的大小放进小根堆里。建一棵线段树存区间l+num的最大值,并且维护这个最大值出现的最大位置(l最靠右保证最短)。
l+num只有小于或等于这两种可能,所以只可能是max=r,所以最大值就可以。
每次把以i为右端点的询问倒进待询问的小根堆里,查询[1,l]中是否有满足条件的,满足就找到了答案,不满足了就直接break
至于为什么要把所有询问按右边界的大小放进小根堆里,是因为待询问中r最小的都不符合了,那其他更不可能符合,画图感受一下。(右边不可能比左边多)
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
struct node
{
int l,r,id;
friend bool operator < (node a,node b){
return a.l==b.l?a.r>b.r:a.l<b.l;
}
}h[],ans[];
struct tree
{
int l,r,mx,pos,lz;
}t[];
int n,m,a[],pos[];
vector<node> ve[];
priority_queue<node>q;
void update(int x)
{
t[x].mx=max(t[x*].mx,t[x*+].mx);
t[x].pos=t[x*].mx>t[x*+].mx?t[x*].pos:t[x*+].pos;
}
void build(int x,int l,int r)
{
t[x].l=l;t[x].r=r;
if(l==r){
t[x].mx=l;
t[x].pos=l;
return;
}
int mid=(l+r)>>;
build(x*,l,mid);
build(x*+,mid+,r);
update(x);
}
void pushdown(int x)
{
if(t[x].lz){
t[x*].mx+=t[x].lz;t[x*+].mx+=t[x].lz;
t[x*].lz+=t[x].lz;t[x*+].lz+=t[x].lz;
t[x].lz=;
}
}
void add(int x,int l,int r)
{
if(l<=t[x].l&&r>=t[x].r){
t[x].mx++;
t[x].lz++;
return;
}
pushdown(x);
int mid=(t[x].l+t[x].r)>>;
if(l<=mid) add(x*,l,r);
if(r>mid) add(x*+,l,r);
update(x);
}
int query(int x,int l,int r,int w)
{
if(t[x].mx<w) return -;
if(l<=t[x].l&&r>=t[x].r) return t[x].pos;
pushdown(x);
int mid=(t[x].l+t[x].r)>>,as=-;
if(l<=mid) as=max(as,query(x*,l,r,w));
if(r>mid) as=max(as,query(x*+,l,r,w));
return as;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
scanf("%d",&m);
for(int i=;i<=m;i++){
scanf("%d%d",&h[i].l,&h[i].r);
h[i].id=i;
ve[h[i].r].push_back(h[i]);
}
build(,,n);
for(int i=;i<=n;i++){
if(a[i]>&&pos[a[i]-]<i) add(,,pos[a[i]-]);
if(a[i]<n&&pos[a[i]+]<i) add(,,pos[a[i]+]);
for(int j=;j<ve[i].size();j++) q.push(ve[i][j]);
while(q.size()){
node hh=q.top();
int as=query(,,hh.l,i);
if(as==-) break;
ans[hh.id].l=as;ans[hh.id].r=i;
q.pop();
}
}
for(int i=;i<=m;i++) printf("%d %d\n",ans[i].l,ans[i].r);
return ;
}
优美序列
这个出题人好像很喜欢线段树和网格嘞
8.5 NOIP模拟测试13 矩阵游戏+跳房子+优美序列的更多相关文章
- NOIP模拟测试13「矩阵游戏·跳房子·优美序列」
矩阵游戏 考试时思路一度和正解一样,考试到最后还是打了80分思路,结果80分打炸了只得了40分暴力分 题解 算出来第一列的总值,每次通过加每两列之间的差值得出下一列的总值 算第一列我们只需要让当前点* ...
- NOIP模拟测试13
考得还算可以,T3还有提升空间(没看清题&&样例没过 拿了4分). 期望得分:80+40+0=120 实际得分:80+85+4=169 一脸黑线.....是数据比较水的原因,T2分都比 ...
- 2019.8.5 NOIP模拟测试13 反思总结【已更新完毕】
还没改完题,先留个坑. 放一下AC了的代码,其他东西之后说… 改完了 快下课了先扔代码 跑了跑了 思路慢慢写 来补完了[x 刚刚才发现自己打错了标题 这次考试挺爆炸的XD除了T3老老实实打暴力拿了52 ...
- 8.5 NOIP 模拟测试 13
今天的考试说实话T1很简单没A,我是傻X.T2T3难得一批,但是暴力的分还是拿了! 总结一下就是:骗分过样例,暴力出奇迹!只要瞎搞就行了! 话说现在终于不像之前那么傻了,终于知道打暴力了,因为之前暴力 ...
- NOIP模拟测试17&18
NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...
- 「题解」NOIP模拟测试题解乱写II(36)
毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)
2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组
2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色
2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...
随机推荐
- Vue.js 源码分析(十七) 指令篇 v-if、v-else-if和v-else 指令详解
v-if 指令用于条件性地渲染一块内容.这块内容只会在指令的表达式返回true值的时候被渲染. v-else-if,顾名思义,充当 v-if 的“else-if 块”,可以连续使用: 也可以使用 v- ...
- Tensorflow源码解析2 -- 前后端连接的桥梁 - Session
Session概述 1. Session是TensorFlow前后端连接的桥梁.用户利用session使得client能够与master的执行引擎建立连接,并通过session.run()来触发一次计 ...
- sitecore 如何创建一个渠道分类
您可以通过渠道跟踪联系人与您的品牌的所有互动.您可以将渠道与广告系列活动相关联,以便跟踪联系人与您的品牌互动的方式.通过比较各个渠道的目标转化率,您可以了解哪些渠道可以带来更好的联系参与度.您可以在体 ...
- 在IT产品白皮书中遇到的缩略词
在IT产品白皮书中遇到的缩略词 更新中...
- Oracle 原生驱动带来的精度问题的分析与解决
问题 Oracle 官方提供了 dotnet core 驱动,但我们在使用中遇到了精度问题. 复现 以下代码运行数学运算 1/3,无论是 OracleCommand.ExecuteScalar() 还 ...
- CSS 控制文字两端对齐
<html> <head> <style> td:after { content: ''; } td p{ font-size: 14px; width: 5em; ...
- 【10】Nginx:后面有无 / 的区别
写在前面的话 在 nginx 中,我们很多时候都有一个疑问,在 proxy_pass 或者 root 或者 location 后面需不需要加上 /,加和不加有啥区别. root / alias 后面 ...
- 我的Xamarin开发配置
我用的的是VS2019 步骤1:打开VS→工具→Android→Android SDK 管理器 安装平台的 Android 9.0-pie下的Android SDK Platform 28 和 Goo ...
- 3-美团 HTTP 服务治理实践
参考: 美团 HTTP 服务治理实践 Oceanus:美团HTTP流量定制化路由的实践
- LinuxShell——正则表达式
LinuxShell——正则表达式 摘要:本文主要学习了Shell中的正则表达式. 简介 含义 正则表达式,也称作正规表示法,是用于描述字符排列和匹配模式的一种语法规则,它主要用于字符串的模式分割.匹 ...