矩阵游戏

考试时思路一度和正解一样,考试到最后还是打了80分思路,结果80分打炸了只得了40分暴力分

题解

算出来第一列的总值,每次通过加每两列之间的差值得出下一列的总值

算第一列我们只需要让当前点*行增倍的数量就行了

    for(ll i=1;i<=n;i++){
nowlie=(nowlie+elephant(i,1)*hang[i])%mod;
sum=(sum+hang[i]);
}

算其他列

        nowlie=(nowlie+sum)%mod;

可能这一列会加倍只需乘上就行了

        ans=(ans+nowlie*lie[i])%mod;

思路简单代码好打,然而考试我还是打炸了

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1010101
const ll mod=1e9+7;
ll n,m,nowlie=0,sum=0,ans=0,k;
ll lie[A],hang[A];
char c[5];
ll elephant(ll i,ll j){
return ((i-1)*m%mod+j)%mod;
}
int main(){
scanf("%lld%lld%lld",&n,&m,&k);
for(ll i=1;i<=1000000;i++){
hang[i]=1;
lie[i]=1;
}
for(ll i=1,a,x;i<=k;i++){
scanf("%s",c+1);
scanf("%lld%lld",&a,&x);
if(c[1]=='S'){
lie[a]=lie[a]*x%mod;
}
if(c[1]=='R'){
hang[a]=hang[a]*x%mod;
}
}
for(ll i=1;i<=n;i++){
nowlie=(nowlie+elephant(i,1)*hang[i])%mod;
sum=(sum+hang[i]);
}
for(ll i=1;i<=m;i++){
ans=(ans+nowlie*lie[i])%mod;
nowlie=(nowlie+sum)%mod;
}
cout<<ans<<endl;
}

跳房子

莫名和考试时思路相似   其实一点也不相似

$85\%$算法

暴力找循环节,剩下数据经过特殊构造你AC不了的,,,,,,,,,

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
char s[10];
#define A 11111111
ll vis[5100][5100],a[5100][5100];
inline int read(){
register int ret=0,f=1;
register char r;
r=getchar();
while(!isdigit(r)){
if(r=='-') f=-1;
r=getchar();
}
while(isdigit(r)){
ret=ret*10+r-'0';
r=getchar();
}
return f*ret;
}
ll p,nowx=1,nowy=1,top=0,n,m;
ll stax[A],stay[A];
void work(ll x){
ll tot=0;
while(x){
ll nx=nowx,ny=nowy,d2=nx+1,d3=nx-1;
(nx+1==n+1)?d2=1:d2=nx+1;
(nx-1==0)?d3=n:d3=nx-1;
if(ny==m) ny=0;
ll z1=a[nx][ny+1],z2=a[d2][ny+1],z3=a[d3][ny+1];
if(z1>z2&&z1>z3) nowx=nx,nowy=ny+1;
else if(z2>z1&&z2>z3) nowx=d2,nowy=ny+1;
else if(z3>z1&&z3>z2) nowx=d3,nowy=ny+1;
x--;
top++;stax[top]=nowx,stay[top]=nowy;
if(!vis[nowx][nowy])
vis[nowx][nowy]=top;
else{
tot=top-vis[nowx][nowy];
x=x%tot;
}
}
while(top){
ll x=stax[top],y=stay[top];
vis[x][y]=0;
top--;
}
printf("%lld %lld\n",nowx,nowy);
}
int main(){
n=read(),m=read();
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
a[i][j]=read();
p=read();
for(ll i=1,aa,bb,cc;i<=p;i++){
scanf("%s",s+1);
if(s[1]=='m'){
cc=read();
work(cc);
}
if(s[1]=='c'){
aa=read(),bb=read(),cc=read();
a[aa][bb]=cc;
}
}
}

$100\%$算法

和找循环节类似但又有很大区别,

思考循环节问题出现在那?

可能会遍历整张图才找到一个循环节,即使你预处理了找到循环节,那么出现change正好改掉循环节,再move找循环节,再change 再move你就被卡死了,复杂度本身就有问题

那么没办法做了吗

建立置换,走到一个点,如果步数大就直接置换,步数小就暴力走

我们用一个线段树来维护这个置换如果从1--m建树,那么t[1]就表示走m步置换成哪里

每次走m步

走的次数就是v/m

根据置换的运算$t^k$就是走了k次每次走t步

通过快速幂算出置换得出结果

那么我们经过%可以快速算出来剩下的,剩下的步数暴力走即可

顺便学了置换的运算

c.g[i]=a.g[t.g[i]];

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1010101
ll n,m,k,nowx=1,nowy=1;
ll f[2100][2100];
char znsbc[10];
struct node{
ll g[2100];
node(){
for(ll i=1;i<=n;i++)
g[i]=i;
}
node operator *(const node &a){
node t=*this,c;
for(ll i=1;i<=n;i++)
c.g[i]=a.g[t.g[i]];
return c;
}
}nxt[2100];
struct tree{
ll l,r,f;
node t;
}tr[10100];
inline void up(ll p){
tr[p].t=tr[p<<1].t*tr[p<<1|1].t;
return ;
}
inline void built(ll p,ll l,ll r){
tr[p].l=l,tr[p].r=r;
if(l==r){
tr[p].t=nxt[l];
return ;
}
ll mid=(l+r)>>1;
built(p<<1,l,mid);
built(p<<1|1,mid+1,r);
up(p);
}
inline void add(ll p,ll o){
// printf("l=%lld r=%lld\n",l,r);
if(tr[p].l==tr[p].r){
tr[p].t=nxt[o];
return ;
}
ll mid=(tr[p].l+tr[p].r)>>1;
if(mid>=o)
add(p<<1,o);
else
add(p<<1|1,o);
up(p);
}
inline node meng(node x,ll k){
node ans;
for(;k;k>>=1,x=x*x)
if(k&1)
ans=ans*x;
return ans;
}
inline ll get(ll k,ll flag){
if(k==(flag?m+1:n+1))
return 1;
if(!k)
return flag?m:n;
return k;
}
inline void change(ll xx,ll yy){
ll maxn=0;
xx=get(xx,0);
yy=get(yy,1);
for(ll i=-1;i<=1;i++){
ll x=get(xx+i,0),y=get(yy+1,1);
if(maxn<f[x][y]) maxn=f[x][y],nxt[yy].g[xx]=x;
}
return ;
}
inline void move(ll x){
while(x)
x--,nowx=nxt[nowy].g[nowx],nowy=get(nowy+1,1)/*,printf("x=%lld\n",x)*/;
}
int main(){
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
scanf("%lld",&f[i][j]);
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
change(i,j);
built(1,1,m);
scanf("%lld",&k);
for(ll i=1,a,b,c,v,o;i<=k;i++){
scanf("%s",znsbc+1);
if(znsbc[1]=='m'){
scanf("%lld",&v);
ll len=min(v,m-nowy+1);
move(len);
v-=len;
if(v){
nowx=meng(tr[1].t,v/m).g[nowx];
v%=m;
if(v){
move(v);
}
}
printf("%lld %lld\n",nowx,nowy);
}
else{
scanf("%lld%lld%lld",&a,&b,&c);
f[a][b]=c;
for(ll j=-1;j<=1;j++)
change(a+j,b-1)/*,printf("*****\n");*/;
o=get(b-1,1);
add(1,o);
}
}
}

随机数据生成

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll random(ll n)
{
return rand()%n;
}
bool a[3210520];
int main()
{
freopen("mkd.txt","w",stdout);
srand((unsigned)time(0));
ll n=random(5)+5,m=random(5)+5;
printf("%lld %lld\n",n,m);
for(ll i=1;i<=n;i++,puts(""))
for(ll j=1;j<=m;j++){
ll x=random(550);
while(a[x]) x=random(550);
printf("%lld ",x);
}
ll k=random(50)+50;
printf("%lld\n",k);
for(ll i=1;i<=k;i++)
{
ll op=random(2);
if(op) {
printf("move ");
printf("%lld\n",random(50000)+50000);
}
else{
printf("change ");
ll l=random(n)+1;
ll r=random(m)+1;
printf("%lld %lld %lld\n",l,r,random(50)+50);
}
}
fclose(stdout);
}

t3做法尤其玄学

做法1,把序列问题转化为图论????????线段树优化建边+tarjan缩点+线段树维护图中内容我不会

做法2,扫描线,一条性质,若a<=b<=c<=d并且a--c是好区间,b--d是好区间,那么a--d是好区间

假设我们扫描到i i+1,那么如果i i+1在好区间里,那么val[i] val[i+1]都在好区间里,

设好的二元组为相邻两个数,那么区间若为好区间好二元组数量为r-l

用一棵线段树维护二元组数量设为v,若v+l=r则是好区间,假设我们当前扫描到了a[i],那么处于a[i]-1  a[i]+1的位置都要加1

线段树维护一下,细节比较多

做法3,性质若r-l=maxval-minval那么就是一个好区间

那么若maxval到minval之间全部出现那么是一个好区间,那么位置最左最右值出现即可,,

线段树维护一下||st表维护一下

但做法3本身复杂度不对,随机数据下表现优秀,但会被特殊数据卡

分块优化一下

#include<bits/stdc++.h>
#define MAXN 100005
#define min(a,b) ((a<b)?(a):(b))
#define max(a,b) ((a>b)?(a):(b))
using namespace std;
int mn[20][MAXN],mx[20][MAXN],mh[MAXN],a[MAXN],n,mnpos[20][MAXN],mxpos[20][MAXN],ans1[2005][2005],ans2[2005][2005],t;
int bl[MAXN];
vector<int>ld;
void pre()
{
for(int i=1;i<=n;i++)
for(int j=17;j>=0;j--)
if(i>=(1<<j))
{
mh[i]=j;
break;
}
for(int i=1;i<=17;++i)
for(int j=1;j<=n;++j)
{
mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<(i-1))]);
mx[i][j]=max(mx[i-1][j],mx[i-1][j+(1<<(i-1))]);
mnpos[i][j]=min(mnpos[i-1][j],mnpos[i-1][j+(1<<(i-1))]);
mxpos[i][j]=max(mxpos[i-1][j],mxpos[i-1][j+(1<<(i-1))]);
}
return ;
}
/*const int L=1<<20|1;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)*/
inline int Rd()
{
int x=0;char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
return x;
}
inline int gmax(int l,int r)
{
return max(mx[mh[r-l+1]][l],mx[mh[r-l+1]][r-(1<<mh[r-l+1])+1]);
}
inline int gmin(int l,int r)
{
return min(mn[mh[r-l+1]][l],mn[mh[r-l+1]][r-(1<<mh[r-l+1])+1]);
}
inline int qmax(int l,int r)
{
return max(mxpos[mh[r-l+1]][l],mxpos[mh[r-l+1]][r-(1<<mh[r-l+1])+1]);
}
inline int qmin(int l,int r)
{
return min(mnpos[mh[r-l+1]][l],mnpos[mh[r-l+1]][r-(1<<mh[r-l+1])+1]);
}
int main()
{
// freopen("sequence21.in","r",stdin);
n=Rd();
t=pow(n,0.7);
for(int i=1;i<=n;i++)
{
a[i]=Rd();
mn[0][i]=mx[0][i]=a[i];
mnpos[0][a[i]]=mxpos[0][a[i]]=i;
}
int p=0,tot=0;
while(p<n)
{
ld.push_back(p+1);
for(int i=1;i<=t;i++)bl[p+i]=tot;
p+=t;
tot++;
}
pre();
memset(ans1,0x3f,sizeof(ans1));
memset(ans2,-0x3f,sizeof(ans2));
for(int i=0;i<ld.size();i++)
for(int j=i;j<ld.size();j++)
{
int l,r;
l=ld[i];
r=ld[j];
int nowmin=gmin(l,r),nowmax=gmax(l,r);
int pl=qmin(nowmin,nowmax),pr=qmax(nowmin,nowmax);
while(l>pl||r<pr)
{
if(l>pl)
{
nowmin=min(nowmin,gmin(pl,l));
nowmax=max(nowmax,gmax(pl,l));
l=pl;
}
if(r<pr)
{
nowmin=min(nowmin,gmin(r,pr));
nowmax=max(nowmax,gmax(r,pr));
r=pr;
}
pl=qmin(nowmin,nowmax);pr=qmax(nowmin,nowmax);
}
ans1[i][j]=l;ans2[i][j]=r;
// cout<<ans1[i][j]<<' '<<ans2[i][j]<<endl;
}
int Q;
Q=Rd();
while(Q--)
{
register int l,r,ll,rr;
l=Rd();r=Rd();
ll=bl[l]+1;rr=bl[r]-1;
int nowmin=gmin(l,r),nowmax=gmax(l,r);
int pl=qmin(nowmin,nowmax),pr=qmax(nowmin,nowmax);
while(l>pl||r<pr)
{
ll=bl[l]+1;rr=bl[r]-1;
if(l>pl)
{
nowmin=min(nowmin,gmin(pl,l));
nowmax=max(nowmax,gmax(pl,l));
l=pl;
l=min(l,ans1[ll][rr]);
}
if(r<pr)
{
nowmin=min(nowmin,gmin(r,pr));
nowmax=max(nowmax,gmax(r,pr));
r=pr;
r=max(r,ans2[ll][rr]);
}
pl=qmin(nowmin,nowmax);pr=qmax(nowmin,nowmax);
}
printf("%d %d\n",l,r);
}
return 0;
}

NOIP模拟测试13「矩阵游戏&#183;跳房子&#183;优美序列」的更多相关文章

  1. NOIP模拟测试24「star way to hevaen·lost my music」

    star way to heaven 题解 大致尝试了一下并查集,记忆化搜索,最小生成树 最小生成树是正解,跑最小生成树然后找到最大的值 欧几里德距离最小生成树学习 prim楞跑 至于为什么跑最小生成 ...

  2. 8.5 NOIP模拟测试13 矩阵游戏+跳房子+优美序列

    T1矩阵游戏 数学题.首先这一列这一行先乘还是后乘对最后答案没有影响.a[i][j]表示矩阵中原始的值,h[i]表示i行的累乘,l[i]表示i列的累乘.易得ans=Σa[i][j]*h[i]*l[i] ...

  3. NOIP模拟测试13

    考得还算可以,T3还有提升空间(没看清题&&样例没过 拿了4分). 期望得分:80+40+0=120 实际得分:80+85+4=169 一脸黑线.....是数据比较水的原因,T2分都比 ...

  4. 2019.8.5 NOIP模拟测试13 反思总结【已更新完毕】

    还没改完题,先留个坑. 放一下AC了的代码,其他东西之后说… 改完了 快下课了先扔代码 跑了跑了 思路慢慢写 来补完了[x 刚刚才发现自己打错了标题 这次考试挺爆炸的XD除了T3老老实实打暴力拿了52 ...

  5. NOIP模拟测试19「count·dinner·chess」

    反思: 我考得最炸的一次 怎么说呢?简单的两个题0分,稍难(我还不敢说难,肯定又有人喷我)42分 前10分钟看T1,不会,觉得不可做,完全不可做,把它跳了 最后10分钟看T1,发现一个有点用的性质,仍 ...

  6. 8.5 NOIP 模拟测试 13

    今天的考试说实话T1很简单没A,我是傻X.T2T3难得一批,但是暴力的分还是拿了! 总结一下就是:骗分过样例,暴力出奇迹!只要瞎搞就行了! 话说现在终于不像之前那么傻了,终于知道打暴力了,因为之前暴力 ...

  7. NOIP模拟测试21「折纸&#183;不等式」

    折纸 题解 考试时无限接近正解,然而最终也只是接近而已了 考虑模拟会爆炸,拿手折纸条试一试,很简单 考你动手能力 代码 #include<bits/stdc++.h> using name ...

  8. NOIP模拟测试17「入阵曲&#183;将军令&#183;星空」

    入阵曲 题解 应用了一种美妙移项思想, 我们先考虑在一维上的做法 维护前缀和$(sum[r]-sum[l-1])\%k==0$可以转化为 $sum[r]\% k==sum[l-1]\%k$开个桶维护一 ...

  9. NOIP模拟测试11「string&#183;matrix&#183;big」

    打的big出了点小问题,maxx初值我设的0然后少了10分 第二题暴力打炸 第一题剪了一些没用的枝依然40分 总分70 这是一次失败的考试 string 想到和序列那个题很像,但我没做序列,考场回忆学 ...

随机推荐

  1. 数据人必读!玩转数据可视化用这个就够了——高德LOCA API 2.0升级来袭!

    引言 "一图胜千言",大数据时代来临,数据与人们生活密切相关.复杂难懂且体量庞大的数据给人的感觉总是冷冰冰的,让人难以获取到重点信息,也找不出规律和特征,数据价值发挥不出来.空间数 ...

  2. 基于python对B站收藏夹按照视频发布时间进行排序

    基于python对B站收藏夹按照视频发布时间进行排序 前言 在最一开始,我的B站收藏一直是存放在默认收藏夹中,但是随着视频收藏的越来越多,没有分类的视频放在一起,想在众多视频中找到想要的视频非常困难, ...

  3. ElasticSearch7使用指导

    目录结构: 一.es概述 二.es安装/head插件安装/kibana安装 三.es核心概念 四.IK分词器 五.RestFul操作 六.CRUD(增删改查) 七.Springboot集成es --- ...

  4. Spring AOP获取不了增强类(额外方法)或无法通过getBean()获取对象

    Spring AOP获取不了增强类(额外方法)和无法通过getBean()获取对象 今天在学习AOP发现一个小问题 Spring AOP获取不了额外方法,左思右想发现是接口上出了问题 先上代码 获取不 ...

  5. qemu:///system 没有连接驱动器可用;读取数据时进入文件终点: 输入/输出错误

    原因 1. KVM的相关包 装少了 2KVM的相关包 重新安装 3 May 31 15:22:55 localhost libvirtd: 2019-05-31 07:22:55.554+0000: ...

  6. centos7下cups + samba共打印服务

    centos7下cups + samba共打印服务 2015年8月21日admin发表评论阅读评论   这个算是rhce课程的篇外篇,Samba除了提供文件共享外,也可以像windows下的共享一样提 ...

  7. Vim安装记录

    Vim安装记录 参考链接 安装命令 1. 安装依赖库 2. 下载最新vim源码 3. 删除旧版vim 4. 配置configure.编译.安装 5. 设置vim为默认编辑器 6. 必要的配置 Vim安 ...

  8. Linux下使用bcwipe擦除磁盘空间

    Linux下使用bcwipe擦除磁盘空间 2 Replies 如果要彻底删除硬盘上的文件,Windows下有磁盘粉碎机,bcwipe等. Linux下,也有bcwipe,而且功能更强大. 擦除磁盘剩余 ...

  9. Linux巡检常用命令

    # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # hostn ...

  10. Alien 魔法:RPM 和 DEB 互转

    Alien 魔法:RPM 和 DEB 互转 作者: Gabriel Cánepa 译者: LCTT joeren | 2015-08-31 10:45   评论: 6 收藏: 10 正如我确信,你们一 ...