A.math

考场乱搞拿了95,2333。

考虑裴蜀定理:$ax+by=z$存在整数解,当且仅当$gcd(a,b)|z$。

那么如果某个数能够被拼出来,就必须满足所有$a_i$的$gcd$是它的因子。直接枚举倍数即可。

//代码来自DeepinC
#include<cstdio>
int n,k,g,x;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main(){scanf("%d%d",&n,&k);g=k;while(n--)scanf("%d",&x),g=gcd(g,x);printf("%d\n",k/g);for(int i=0;i<k;i+=g)printf("%d ",i);
}

B.biology

首先将$a[i][j]$离散化,值相同的方格坐标都放到一起。然后很容易得到一个暴力的dp:$f[i][j]=max{f[i'][j']+|i-i'|+|j-j'|}$,$i',j'$位于a值比$i,j$小的上一层。

最劣复杂度会达到$O(n^2m^2)$,考虑优化。可以把绝对值用分类讨论拆开,四个树状数组分别维护$f[i][j]-i-j,f[i][j]-i+j,f[i][j]+i-j,f[i][j]+i+j$的最大值,转移时先分别查询以$i,j$为中心的四块区域的最优值,用最大的更新$f[i][j]$,之后再分别把$f[i][j]$上传到树状数组里。注意要用前缀最大值查询四块的最优值来保证log的复杂度,所以需要把坐标反转一下。

正解其实就是把树状数组去掉……我们用树状数组维护四部分的最大值是为了保证在合法的情况下转移最优,但本题的特殊性使不合法的情况一定没有合法情况优(如果你绝对值去的不对就会让坐标差变成负的),所以直接用四个变量维护四部分的最大值即可。我把坐标转换了一下,即$(i,j)->(i+j,i-j)$,其实不转换也是可以的。

//80分树状数组
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#define pa pair<int,int>
#define QWQ dp[x][y]=max(dp[x][y],maxx)
using namespace std;
typedef long long ll;
int read()
{int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*f;
}
const int N=2005,M=1e6+5;
int n,m;
int a[N][N],b[N][N];
struct bit
{ll c[N][N];int lb(int x){return x&-x;}void update(int x,int y,ll val){for(int i=x;i<=n;i+=lb(i))for(int j=y;j<=m;j+=lb(j))c[i][j]=max(val,c[i][j]);}ll query(int x,int y){ll res=0;for(int i=x;i;i-=lb(i))for(int j=y;j;j-=lb(j))res=max(res,c[i][j]);return res;}
}c1,c2,c3,c4;
int app[M],key[M],cnt,num[M];
vector<pa> fl[M];
ll dp[N][N];
int main()
{n=read();m=read();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){a[i][j]=read();if(!app[a[i][j]]&&a[i][j]){app[a[i][j]]=1;num[++cnt]=a[i][j];}}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b[i][j]=read();sort(num+1,num+cnt+1);for(int i=1;i<=cnt;i++)key[num[i]]=i;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(!a[i][j])continue;fl[key[a[i][j]]].push_back(make_pair(i,j));}int sz=fl[1].size();for(int i=0;i<sz;i++){int x=fl[1][i].first,y=fl[1][i].second;c1.update(x,y,b[x][y]-x-y);c2.update(x,m-y+1,b[x][y]-x+y);c3.update(n-x+1,y,b[x][y]+x-y);c4.update(n-x+1,m-y+1,b[x][y]+x+y);}for(int i=2;i<=cnt;i++){sz=fl[i].size();for(int j=0;j<sz;j++){int x=fl[i][j].first,y=fl[i][j].second;ll maxx=0;maxx=c1.query(x,y)+x+y+b[x][y];QWQ;maxx=c2.query(x,m-y+1)+x-y+b[x][y];QWQ;maxx=c3.query(n-x+1,y)-x+y+b[x][y];QWQ;maxx=c4.query(n-x+1,m-y+1)-x-y+b[x][y];QWQ;//cout<<x<<' '<<y<<' '<<dp[x][y]<<endl;}for(int j=0;j<sz;j++){int x=fl[i][j].first,y=fl[i][j].second;c1.update(x,y,dp[x][y]-x-y);c2.update(x,m-y+1,dp[x][y]-x+y);c3.update(n-x+1,y,dp[x][y]+x-y);c4.update(n-x+1,m-y+1,dp[x][y]+x+y);//cout<<x<<' '<<y<<' '<<dp[x][y]<<endl;}}sz=fl[cnt].size();ll ans=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans=max(ans,dp[i][j]);cout<<ans<<endl;return 0;
}

//AC
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#define pa pair<int,int>
using namespace std;
typedef long long ll;
int read()
{int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return x*f;
}
const int N=2005,M=1e6+5;
int n,m;
int a[N][N],b[N][N];
int app[M],key[M],cnt,num[M];
vector<pa> fl[M];
ll dp[N][N];
int getx(int i,int j){return (i+j)/2;}
int gety(int i,int j){return (i-j)/2;}
int main()
{n=read();m=read();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){a[i][j]=read();if(!app[a[i][j]]&&a[i][j]){app[a[i][j]]=1;num[++cnt]=a[i][j];}}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b[i][j]=read();sort(num+1,num+cnt+1);for(int i=1;i<=cnt;i++)key[num[i]]=i;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(!a[i][j])continue;fl[key[a[i][j]]].push_back(make_pair(i+j,i-j));}ll c1=-0x3f3f3f3f,c2=-0x3f3f3f3f,c3=-0x3f3f3f3f,c4=-0x3f3f3f3f;int sz=fl[1].size();for(int i=0;i<sz;i++){int x=fl[1][i].first,y=fl[1][i].second,ox=getx(x,y),oy=gety(x,y);c1=max(c1,1LL*b[ox][oy]-x);c2=max(c2,1LL*b[ox][oy]+x);c3=max(c3,1LL*b[ox][oy]-y);c4=max(c4,1LL*b[ox][oy]+y);}for(int i=2;i<=cnt;i++){sz=fl[i].size();for(int j=0;j<sz;j++){int x=fl[i][j].first,y=fl[i][j].second,ox=getx(x,y),oy=gety(x,y);ll maxx=max(max(c1+ox+oy,c2-ox-oy),max(c3+ox-oy,c4-ox+oy));dp[ox][oy]=maxx+b[ox][oy];}for(int j=0;j<sz;j++){int x=fl[i][j].first,y=fl[i][j].second,ox=getx(x,y),oy=gety(x,y);c1=max(c1,dp[ox][oy]-x);c2=max(c2,dp[ox][oy]+x);c3=max(c3,dp[ox][oy]-y);c4=max(c4,dp[ox][oy]+y);}}ll ans=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans=max(ans,dp[i][j]);cout<<ans<<endl;return 0;
}

C.english

对于每一个$i\in n$,求出$a[i]$作为最大值的范围$[l,r]$,可以用单调栈实现。

维护一个前缀和,$f[x][i]$表示1~x的区间里第i位是1的数有多少个。

用启发式合并的思路,对于每一个区间x,看它的左右儿子区间$[l,x-1]$和$[x+1,r]$哪个长度更大,以右儿子长度大为例:

枚举左区间的每一个数$a[i]$,并枚举它的每一位,如果这一位是0,那么对ans1的贡献就是$2^i \times (f[r][i]-f[x-1]) \times a[x]$。如果是1同理。

对ans2的贡献就是右区间中有多少个数$xor\ a[i]$后$>a[x]$,再乘上$a[x]$。区间问题用可持久化Trie解决。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<stack>
#include<algorithm>
#include<map>
//#define int long long
using namespace std;
int read()
{int x=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;
}
typedef long long ll;
const int N=1e5+5;
const ll mod=1e9+7;
int n,a[N],op;
int le[N],re[N];
ll f[N][22];
stack<int> s;
ll ans1,ans2;
namespace Trie
{int ch[N*22][2],size[N*22],type,root[N];void ins(int pre,int &now,int i,ll x){now=++type;size[now]=size[pre];if(i<0){size[now]++;return ;}int d=(x>>i)&1;ch[now][d^1]=ch[pre][d^1];ins(ch[pre][d],ch[now][d],i-1,x);size[now]=size[ch[now][0]]+size[ch[now][1]];return ;}void ins(ll x,int pos){ins(root[pos-1],root[pos],20,x);}ll query(int x,int y,int pos){int p=root[pos],res=0;for(int i=20;i>=0;i--){int a=(x>>i)&1,b=(y>>i)&1;if(b==0){res+=size[ch[p][a^1]];p=ch[p][a];}else p=ch[p][a^1];if(!p)break;}return res;}
}
void cacl(int k,int l,int r)
{if(k-l<r-k){for(int j=l;j<=k;j++){(ans1+=1LL*a[j]*a[k]%mod*(r-k+1)%mod)%=mod;for(int i=20;i>=0;i--){int now=(a[j]>>i)&1;if(!now)(ans1+=1LL*(1<<i)*(f[r][i]-f[k-1][i])%mod*a[k]%mod)%=mod;else (ans1-=1LL*(1<<i)*(f[r][i]-f[k-1][i])%mod*a[k]%mod)%=mod,ans1=(ans1+mod)%mod;}ans2=(ans2+1LL*(Trie::query(a[j],a[k],r)-Trie::query(a[j],a[k],k-1)+mod)%mod*a[k]%mod)%mod;}}else{for(int j=k;j<=r;j++){(ans1+=1LL*a[j]*a[k]%mod*(k-l+1)%mod)%=mod;for(int i=20;i>=0;i--){int now=(a[j]>>i)&1;if(!now)(ans1+=1LL*(1<<i)*(f[k][i]-f[l-1][i])%mod*a[k]%mod)%=mod;else (ans1-=1LL*(1<<i)*(f[k][i]-f[l-1][i])%mod*a[k]%mod)%=mod,ans1=(ans1+mod)%mod;}ans2=(ans2+1LL*(Trie::query(a[j],a[k],k)-Trie::query(a[j],a[k],l-1)+mod)%mod*a[k]%mod)%mod;}}
}signed main()
{n=read();op=read();for(int i=1;i<=n;i++)a[i]=read(),Trie::ins(a[i],i);for(int i=1;i<=n;i++){for(int j=0;j<=20;j++){f[i][j]+=f[i-1][j];if((a[i]>>j)&1)f[i][j]++;}}for(int i=1;i<=n;i++){while(!s.empty()&&a[i]>a[s.top()])s.pop();le[i]=s.empty()?1:s.top()+1;s.push(i);}while(!s.empty())s.pop();for(int i=n;i;i--){while(!s.empty()&&a[i]>=a[s.top()])s.pop();re[i]=s.empty()?n:s.top()-1;s.push(i);}for(int i=1;i<=n;i++)cacl(i,le[i],re[i]);if(op==1||op==3)cout<<ans1<<endl;if(op==2||op==3)cout<<ans2<<endl;/*for(int i=1;i<=n;i++)cout<<i<<' '<<le[i]<<' '<<re[i]<<endl;*/return 0;
}
/*
g++ -std=c++11 1.cpp -o 1
./1
*/

转载于:https://www.cnblogs.com/Rorschach-XR/p/11417604.html

[NOIP模拟测试31]题解相关推荐

  1. [NOIP模拟测试30]题解

    A.Return 出题人大概是怕自己的中文十级没人知道,所以写了这么一个***题面.可能又觉得这题太水怕全场A掉后自己面子过不去,于是又故意把输出格式说的含糊不清.(鬼知道"那么输出-1&q ...

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

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

  3. [NOIP模拟测试9]题(Problem) 题解 (组合数全家桶+dp)

    达哥送分给我我都不要,感觉自己挺牛批. $type=0:$ 跟visit那题类似,枚举横向移动的步数直接推公式: $ans=\sum C_n^i \times C_i^{\frac{i}{2}} \t ...

  4. [NOIP模拟测试3] 建造游乐园 题解(欧拉图性质)

    Orz 出题人石二队爷 我们可以先求出有n个点的联通欧拉图数量,然后使它删或增一条边得到我们要求的方案 也就是让它乘上$C_n^2$ (n个点里选2个点,要么删边要么连边,选择唯一) 那么接下来就是求 ...

  5. [NOIP模拟测试34]反思+题解

    不要陷入思维定势,如果长时间没有突破就要考虑更改大方向. 不要把简单问题复杂化. 做完的题就先放下,不管能拿多少分.不能过一段时间就回来调一下. $Solutions:$ A.次芝麻 因为$n+m$始 ...

  6. [NOIP模拟测试37]反思+题解

    一定要分析清楚复杂度再打!!!窝再也不要花2h20min用暴力对拍暴力啦!!! 雨露均沾(滑稽),尽量避免孤注一掷.先把暴力分拿全再回来刚正解. 即使剩下的时间不多了也优先考虑认真读题+打暴力而非乱搞 ...

  7. [NOIP模拟测试10]辣鸡(ljh) 题解

    首先计算块内贡献,很显然是$(x_2-x_1)*(y_2-y_1)*2$. 然后考虑矩形之间的贡献,sort一遍分类讨论$n^2$暴力即可. 注意考虑边界情况是否能多两个,以及角对角的情况. 另外,排 ...

  8. NOIP模拟测试49·50「养花·折射·画作·施工·蔬菜·联盟」

    一套题 养花 题解 分块\主席树 这里我用的是主席树 查询分段$1-(k-1)$找最大的,能向右找就向右找 for(ll nowl=1,nowr=k-1;nowl<=maxx;nowl+=k,n ...

  9. NOIP模拟测试30「return·one·magic」

    magic 题解 首先原式指数肯定会爆$long$ $long$ 首先根据欧拉定理我们可以将原式换成$N^{\sum\limits_{i=1}^{i<=N} [gcd(i,N)==1] C_{G ...

最新文章

  1. 面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序
  2. 使用TCP的简单C/S程序
  3. go 安装墙外的依赖包报错问题
  4. 开源sip客户端 linux,开源SIP服务器 Kamailio
  5. 关于一些常见智柜问题的分析及解决办法
  6. Layui form 表单验证 基本属性
  7. 远程桌面未知的用户名_电脑在远程桌面连接时出现用户名密码错误该怎么办?...
  8. 适应浏览器自带断点下载
  9. PWM波转DC直流之二阶RC低通滤波器设计
  10. 小白教程:Python爬取12306车票信息以及后期数据处理
  11. C盘清理攻略--拯救你的C盘空间
  12. 美通企业日报 | 乐高在中国大陆已开设100家门店;香港首批虚拟银行的成立如箭在弦...
  13. 顶会速递 | ICLR 2020录用论文之强化学习篇
  14. 基于Python实现可以进制转换和计算阶乘的科学计算器
  15. mysql dba视频课_MySQL DBA专家
  16. 台式机+无线路由 配置 wifi热点
  17. 【C#】基础函数、运算符和表达式
  18. Python将url转换作为合法文件名
  19. 我学ERP 之 金蝶ERP-K3_第4章 销售管理
  20. 华为新旗舰鸿蒙,华为新旗舰6月即将登场!鸿蒙系统+液态镜头,比Mate40更难购买...

热门文章

  1. datastage 函数_DataStage 调用存储过程(含输入输出参数)
  2. 开发一款cad插件需要哪些步骤
  3. C++程序设计基础实验-实验三 类和对象
  4. c语言求fibonacci数列前20,求fibonacci数列的前20个数之和
  5. windows7 安装fastai简易教程
  6. objective-c中 -(void)和+(void) 业精于勤荒于嬉,行成于思毁于随
  7. linux EHCI DRIVER之中断处理函数ehci_irq()分析(一)
  8. SAP 批量修改工艺路线
  9. 来电手机铃声捕获方法
  10. 100行Python代码,做一个打地鼠小游戏