11.01

子段和

题目大意

给定一个长度为 \(n\) 的序列 \(a\) ,\(a_i=\{ -1,0,1 \}\) ,需要将 \(a\) 中的 \(0\) 变为 \(1\) 或 \(-1\) ,使得序列 \(a\) 的最大子段绝对值和最小。

\(1\le n \le 10^6\)

解析

考虑到何为最大子段绝对值和,其为 最大前缀和 \(-\) 最小前缀和

那么我们即需要将最小前缀和最大化的情况下让最大前缀和最小 或 让最大前缀和最小化的情况下让最小前缀和最大。

这里考虑第一种写法。

先让全部 \(0\) 变为 \(1\) ,求出最大最小前缀和,记为 \(x\) 。

那么考虑将一些 \(0\) 由 \(1\) 变为 \(-1\) , 这个 \(0\) 后的所有前缀和都变小 \(2\) ,如果最小前缀和 和 最大前缀和 都在这个 \(0\) 后,那么这个变化没有意义。

同理,将一个 \(0\) 由 \(1\) 变为 \(-1\) 如果不使其后的前缀和小于 \(x\) (影响最小前缀和),那么必定将其变为 \(-1\) 为最优情况(可能降低最大前缀和,不影响最小前缀和)。

考虑到前缀和每次只会减小 \(2\) ,所以对最小前缀和为 \(x-1\) 的情况再做一遍求解即可。

时间复杂度 \(O(n)\)

#include<bits/stdc++.h>
#define maxn 1001001
using namespace std;
char s[maxn];
int a[maxn],sum[maxn],mina[maxn],minx,maxx,b[maxn],ans=1e9,n,k;
int main(){
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
scanf("%s",s+1);n=strlen(s+1);
for(int i=1;i<=n;i++){
if(s[i]=='-')a[i]=-1;
if(s[i]=='0')a[i]=0;
if(s[i]=='1')a[i]=1;
}
for(int i=1;i<=n;i++){
sum[i]=sum[i-1];
if(a[i]==-1)sum[i]--;
else sum[i]++;
}mina[n+1]=1e9;
for(int i=n;i>=1;i--)mina[i]=min(sum[i],mina[i+1]);
int k=0,x=mina[1];
for(int i=1;i<=n;i++){
if(a[i]!=0){b[i]=a[i]; continue;}
if(mina[i]+k>x+1)b[i]=-1,k-=2;
else b[i]=1;
}minx=1e9;maxx=0;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+b[i];
if(sum[i]<minx)minx=sum[i];
if(sum[i]>maxx)maxx=sum[i];
}ans=min(ans,maxx-minx);
k=0;
for(int i=1;i<=n;i++){
if(a[i]!=0){b[i]=a[i]; continue;}
if(mina[i]+k>x)b[i]=-1,k-=2;
else b[i]=1;
}minx=1e9;maxx=0;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+b[i];
if(sum[i]<minx)minx=sum[i];
if(sum[i]>maxx)maxx=sum[i];
}ans=min(maxx-minx,ans);
printf("%d\n",ans);
return 0;
}

序列

题目大意

给定一个长度为 \(n\) 的序列和两个整数 \(a\) 和 \(b\) ,初始序列全为 \(0\) ,每次操作可将连续 \(a\) 个位置的数变为 \(0\) ,或连续 \(b\) 个位置的数变为 \(1\) ,求最终序列有几种情况。答案对 \(10^9+7\) 取模

\(1\le n \le 5000\) ,\(1 \le a,b \le n\)

解析

11.02

题目大意

给定 \(n\) 求 \((1^1+2^2+3^3+……+n^n)\ \ mod \ \ 2^{32}\)

\(1\le n \le 10^9\)

解析

打表(误

分块(误

分块打表(对

对于每段长度 \(10^7\) 的数求前缀和,打出一个长度为 \(10^2\) 的表

段内暴力跑。

#include<bits/stdc++.h>
using namespace std;
#define mod 4294967296
unsigned long long a[1011]={表};
int n,block,o;unsigned long long ans;
unsigned long long qpow(unsigned long long x,unsigned long long y){
unsigned long long ans=1;
while(y){
if(y&1){ans=ans*x;ans%=mod;}
x=(unsigned long long)x*x;x%=mod;y>>=1;
}return ans%mod;
}
int main(){
freopen("mi.in","r",stdin);
freopen("mi.out","w",stdout);
scanf("%d",&n);block=1000000;
ans=a[n/block];
for(int i=n/block*block+1;i<=n;i++)ans+=qpow(i,i),ans%=mod;
cout<<ans<<endl;;
}

最后的数

题目大意

$1\le n \le 10^6 $ , \(a_i=\{0,1,2\}\)

解析

显然最终答案的奇偶性很容易就能判断出来,奇数的话答案就是 \(1\) ,接下来考虑答案为偶数的情况。不难发现,如果某一时刻 \(a\) 中有 \(1\) ,那么操作后 \(a\) 中还有 \(1\) ,或是全为 \(0\) 。

所以只要 \(a\) 中有 \(1\) ,答案为 \(0\) 。

否则将 \(a\) 全体除以 \(2\) ,答案乘以 \(2\) ,再次利用上面的算法即可。

#include<bits/stdc++.h>
#define maxn 1000001
using namespace std;
char s[maxn];
int a[maxn],b[maxn];
int n,l,r,m;
int main(){
freopen("last.in","r",stdin);
freopen("last.out","w",stdout);
scanf("%d",&n);
scanf("%s",s);l=0;r=0;
for(int i=0;i<n;i++)a[i]=s[i]-'0';
for(int i=0;i<n;i++)if(((n-1)&i)==i)l+=(a[i]==1);
if(l&1){cout<<1;return 0;}
for(int i=0;i<n;i++)if(a[i]==1)r=1;
if(r){cout<<0;return 0;}
for(int i=0;i<n;i++)if(((n-1)&i)==i)m+=(a[i]==2);
if(m&1){cout<<2;return 0;}
cout<<0;
}

序列

题目大意

给定一个长度为 \(n\) 的序列 \(a\) 和一个正整数 \(x\)

求序列 \(a\) 有多少个非空子序列使得这个子序列中任意两个数的异或和大于等于 \(x\) .

\(1\le n \le 10^6\) ,\(0\le a_i,x \le 2^{60}\) ,保证 \(a\) 中元素互不相同。答案模 \(998244353\)

解析

一提到异或,可以往 \(Trie\) 树上想

考虑将序列 \(a\) 上的元素一一加入 \(Trie\) 中,每次统计当前元素的贡献。

遍历 \(Trie\) 时,对于当前位如果 \(x\) 为 \(1\) ,那么往反方向走,否则,累加反方向答案,往正方向走。

注意:单独一个元素也要累加进答案

#include<bits/stdc++.h>
#define maxn 6010001
#define mod 998244353
using namespace std;
long long trie[maxn][2],a[maxn],x,w[maxn];
long long ans,c;int n,tot=1;
void add(long long x,long long val){
int u=1;
for(long long i=59;i>=0;i--){
int v=((x>>i)&1);
if(!trie[u][v])trie[u][v]=++tot;
u=trie[u][v];w[u]+=val;w[u]%=mod;
}
}
long long query(long long x,long long y){
long long u=1,ans=0;
for(long long i=59;i>=0;i--){
if(!u)break;
int v=((x>>i)&1);
if((y>>i)&1)u=trie[u][v^1];
else ans+=w[trie[u][v^1]],ans%=mod,u=trie[u][v];
}ans+=w[u];ans%=mod;
return ans;
}
int main(){
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
scanf("%d%lld",&n,&x);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
sort(a+1,a+n+1);a[n+1]=-1;
for(int i=1;i<=n;i++){
long long q=(1+query(a[i],x))%mod;
add(a[i],q);ans+=q;c=1;ans%=mod;
}printf("%lld\n",ans);
return 0;
}

排列

题目大意

\(1\le n \le 12\) , $ 1\le|T|\le 10^6$

解析

瞎 jb pushdown即可

#include<bits/stdc++.h>
#define maxn 1000001
using namespace std;
int trie[maxn][3],ans[maxn],w[maxn],rev[maxn];
int qp[101];
int n,tot=1;
char s[maxn];
void add(int x){
int u=1;
for(int i=0;i<n;i++){
int v=(x/qp[i])%3;
if(!trie[u][v])trie[u][v]=++tot;
u=trie[u][v];
}w[u]=x;
}
void pushdown(int x){
if(!rev[x])return ;
swap(trie[x][1],trie[x][2]);
rev[trie[x][0]]^=1;
rev[trie[x][1]]^=1;
rev[trie[x][2]]^=1;
rev[x]=0;
}
void modify1(){
int u=1;
for(int i=0;i<n;i++){
pushdown(u);
swap(trie[u][1],trie[u][2]);
swap(trie[u][1],trie[u][0]);
u=trie[u][0];
}
}
void modify2(){rev[1]^=1;}
void print(int u,int dep,int S){
if(dep==n){ans[S]=w[u];return ;}
pushdown(u);
print(trie[u][0],dep+1,S);
print(trie[u][1],dep+1,S+qp[dep]);
print(trie[u][2],dep+1,S+qp[dep]*2);
}
int main(){
freopen("perm.in","r",stdin);
freopen("perm.out","w",stdout);
scanf("%d",&n);
scanf("%s",s+1);int slen=strlen(s+1);qp[0]=1;
for(int i=1;i<=n;i++)qp[i]=qp[i-1]*3;
for(int i=0;i<qp[n];i++)add(i);
for(int i=1;i<=slen;i++)if(s[i]=='1')modify1();else modify2();
print(1,0,0);
for(int i=0;i<qp[n];i++)printf("%d ",ans[i]);
return 0;
}

11.04

连续数

题目大意

给定 \(n\) ,求最小的 \(m\) 使得有 \(m(m\ge 2)\) 个连续正整数相加为 \(n\) ,无解输出 \(-1\)

\(1 \le n\le10^9\)

解析

用等差序列公式推一推即可。

#include<bits/stdc++.h>
using namespace std;
int n;bool flag;
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
for(int i=2;i*i<=2*n;i++){
if(((2*n)%i==0)&&((2*n/i-i+1)%2==0)){
flag=1; cout<<i<<endl;
break;
}
}if(flag==0)cout<<-1;
return 0;
}

无向图

题目大意

给定一张 \(n\) 个点 \(m\) 条边的无向图,需要将每条边赋一个权值 \([0,4]\) ,满足对于每一个点,所有与它相连的边权值和为 \(5\) 的倍数。求方案数。可能有重边和自环。答案对 \(998244353\) 取模。

\(1\le n,m \le 10^6\)

解析

对于每个连通块分开讨论,答案为积。

考虑树的情况一定为 \(1\)

如果一个连通块内有奇环,那么答案为 \(5^{|E|-|V|}\)

否则答案为 \(5^{|E|-|V|+1}\)

证明待补……

用二分图染色判奇环即可

#include<bits/stdc++.h>
#define maxn 4100001
#define mod 998244353
using namespace std;
int cnt,from[maxn],to[maxn],head[maxn],Next[maxn],rd[maxn];
int n,m,u,v,vis[maxn],sume,sumv;bool flag;
long long ans;
long long qpow(long long x,long long y){
long long ans=1;
while(y){
if(y&1){ans=ans*x;ans%=mod;}
x=x*x;x%=mod;y>>=1;
}return ans%mod;
}
void add(int u,int v){
cnt++; rd[u]++;
from[cnt]=u; to[cnt]=v;
Next[cnt]=head[u]; head[u]=cnt;
}
void dfs(int u){sumv++;sume+=rd[u];
for(int i=head[u];i!=-1;i=Next[i]){
int v=to[i];
if(vis[v]!=-1){
if(vis[u]!=(vis[v]^1))flag=1;
continue;
}
vis[v]=(vis[u]^1);dfs(v);
}
}
int main(){
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
memset(head,-1,sizeof(head));
memset(vis,-1,sizeof(vis));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}ans=1;
for(int i=1;i<=n;i++){
if(vis[i]==-1){
flag=0;sume=0,sumv=0;
vis[i]=0; dfs(i);sume/=2;
if(flag==1){
ans=(ans*qpow(5,sume-sumv))%mod;ans%=mod;
}else{
ans=(ans*qpow(5,sume-sumv+1))%mod;ans%=mod;
}
}
}printf("%lld\n",ans);
return 0;
}

矩阵

题目大意

\(1\le n\le 500\)

解析

势能分析

每个点初始最短路最大为 \(n\) 级别

对于每次修改,用 \(DFS\) 从修改点进行松弛操作

点每次松弛,点的最短路必定减小

因为点最短路最大为 \(n\) ,所以只会被松弛 \(n\) 次

\(n^2\) 个点只会被松弛 \(n^3\) 次

所以暴力跑 \(DFS\) 即可

#include<bits/stdc++.h>
#define maxn 510
#define inf 1e9
using namespace std;
struct kkk{
int x,y;
};
int n,a[maxn*maxn];
int b[maxn][maxn],vis[maxn][maxn],dis[maxn][maxn];
int res,o,ans;
int tx[5]={0,1,-1,0,0},ty[5]={0,0,0,1,-1};
queue<kkk> q;
void BFS(){
for(int i=1;i<=n;i++)dis[i][n]=0,dis[n][i]=0,dis[1][i]=0,dis[i][1]=0,vis[i][n]=1,vis[n][i]=1,vis[1][i]=1,vis[i][1]=1;
for(int i=1;i<=n;i++)q.push((kkk){i,1});
for(int i=2;i<=n;i++)q.push((kkk){1,i});
for(int i=2;i<=n;i++)q.push((kkk){n,i});
for(int i=2;i<n;i++)q.push((kkk){i,n});
while(!q.empty()){
int ux=q.front().x,uy=q.front().y;q.pop();vis[ux][uy]=0;
for(int i=1;i<=4;i++){
int vx=ux+tx[i],vy=uy+ty[i];
if(dis[vx][vy]>dis[ux][uy]+1){
dis[vx][vy]=dis[ux][uy]+1;
if(!vis[vx][vy]){
vis[vx][vy]=1;
q.push((kkk){vx,vy});
}
}
}
}
}
void dfs(int ux,int uy){
for(int i=1;i<=4;i++){
int vx=ux+tx[i],vy=uy+ty[i];if(vx<=0||vy<=0||vx>n||vy>n)continue;
if(dis[vx][vy]>dis[ux][uy]+b[vx][vy]){
dis[vx][vy]=dis[ux][uy]+b[vx][vy];
dfs(vx,vy);
}
}
}
int main(){
freopen("rec.in","r",stdin);
freopen("rec.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)b[i][j]=1;
for(int i=1;i<=n*n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)dis[i][j]=inf;
BFS();
for(int i=1;i<=n*n;i++){
int x=(a[i]+n-1)/n,y=a[i]-n*(x-1);
ans+=dis[x][y];dis[x][y]--;b[x][y]=0;
//dis[x][y]=max(0,dis[x][y]);
dfs(x,y);
}printf("%d",ans);
}

二元组

题目大意

对于 \(60\%\) 的分数 \(2\le n \le 5000\)

对于 \(100 \%\) 的分数 \(2\le n \le 2*10^5\)

\(1\le A_i,B_i\le10^9\)

解析

不是很会

60分就dp

//60分
#include<bits/stdc++.h>
#define maxn 5010
using namespace std;
int n,a[maxn],b[maxn];
long long f[maxn][maxn],ans;
int main(){
freopen("turple.in","r",stdin);
freopen("turple.out","w",stdout);
memset(f,0x3f,sizeof(f));ans=f[0][0];
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i],&b[i]);
}f[1][0]=0;f[0][1]=0;f[0][0]=0;
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
int k=max(i,j)+1;
if(i==j)continue;
if(k!=i) if(j!=0) f[i][k]=min(f[i][k],f[i][j]+abs(a[j]-a[k])+abs(b[j]-b[k])); else f[i][k]=min(f[i][k],f[i][j]);
if(k!=j) if(i!=0) f[k][j]=min(f[k][j],f[i][j]+abs(a[i]-a[k])+abs(b[i]-b[k])); else f[k][j]=min(f[k][j],f[i][j]);
}
}
for(int i=0;i<=n;i++)ans=min(ans,min(f[i][n],f[n][i]));
cout<<ans<<endl;
return 0;
}

NOIP集训题目解析的更多相关文章

  1. 1Z0-053 争议题目解析

    1Z0-053 争议题目解析 Summary 题目NO. 题目解析链接地址 题库答案 参考答案 考查知识点  24 http://www.cnblogs.com/jyzhao/p/5319220.ht ...

  2. 1Z0-053 争议题目解析25

    1Z0-053 争议题目解析25 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 25.You enabled Flashback Data Archive on the INVEN ...

  3. 1Z0-053 争议题目解析24

    1Z0-053 争议题目解析24 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 24.Which of the following information will be gath ...

  4. 1Z0-053 争议题目解析46

    1Z0-053 争议题目解析46 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 46.What happens when you run the SQL Tuning Adviso ...

  5. 1Z0-053 争议题目解析86

    1Z0-053 争议题目解析86 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 86.Your production database is running in archivel ...

  6. 1Z0-053 争议题目解析134

    1Z0-053 争议题目解析134 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 134.You are managing an Oracle Database 11g datab ...

  7. 1Z0-053 争议题目解析154

    1Z0-053 争议题目解析154 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 154.A database is running in ARCHIVELOG mode and ...

  8. 1Z0-053 争议题目解析175

    1Z0-053 争议题目解析175 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 175.You are peer reviewing a fellow DBAs backup p ...

  9. 1Z0-053 争议题目解析212

    1Z0-053 争议题目解析212 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 212.Note the following parameters settings in you ...

随机推荐

  1. 抓包神器 tcpdump 使用介绍 (转)

    tcpdump 命令使用简介 简单介绍 tcpdump 是一款强大的网络抓包工具,运行在 linux 平台上.熟悉 tcpdump 的使用能够帮助你分析.调试网络数据. 要想使用很好地掌握 tcpdu ...

  2. springboot实现分布式锁(spring integration,redis)

    Springboot实现分布式锁(Spring Integration+Redis) 一.在项目的pom.xml中添加相关依赖 1)Spring Integration依赖 <dependenc ...

  3. C预备知识_001

    程序由什么构成? 1.对数据的描述:在程序中要指定用到哪些数据以及这些数据的类型和数据的组织形式,其实这就是数据结构(data structure). 2.对操作的描述:即要求计算机就行操作的步骤,也 ...

  4. Java注解和注解处理器使用方法

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11492274.html 准备材料: 实体类: PrintDemo 注解类: PrintName ...

  5. python基础语法_2基本数据类型

    http://www.runoob.com/python3   大纲 Number(数字) String(字符串) List(列表) Tuple(元组) Sets(集合) Dictionarys(字典 ...

  6. node 解决存储xss风险报告

    1. 安装 xss模块 npm install xss 2.在 Node.js 中使用 const xss = require("xss"); // 在项目的接口里面添加 let ...

  7. 帆软报表(finereport)禁用右键

    点击模板>模板web属性>(填报,数据分析,分页预览设置),选择为该模板单独设置,在下面的事件设置里面添加一个加载结束事件,完整js代码如下: 这段代码的基本原理是让用户的页面右键点击事件 ...

  8. 6U VPX i7 刀片计算机

    一.产品概述 该产品是一款基于第三代Intel i7双核四线程(或四核八线程)的高性能6U VPX刀片式计算机.产品提供了可支持全网状交换的高速数据通道,其中P1,P2各支持4个PCIe x4 Gen ...

  9. Spring Boot数据访问之数据源自动配置

    Spring Boot提供自动配置的数据访问,首先体验下,Spring Boot使用2.5.5版本: 1)导入坐标: 2.5.25版本支持8.0.26mysql数据库驱动.spring-boot-st ...

  10. gdb调试小技巧

    1.进入gdb,需要源码,然后gdb+可执行文件,如果要看代码一起的就gdb+可执行文件+tui 2.设置参数 set args +参数 3.设置断点,可以b +行数或者b+函数名字 4.r就是一直跑 ...