(杭电多校)2023“钉耙编程”中国大学生算法设计超级联赛(6)

1001 Count

当k在区间(1+n)/2的左边时,如图,[1,k]和[n-k+1,n]完全相同,所以就m^(n-k)

当k在区间(1+n)/2的右边时,如图,[1,n-k+1]和[k,n]完全相同,所以也是m^(n-k) 

 

别忘了特判,当k等于n时,n-k为0,然后a1=a1,a2=a2,..an=an,所以没什么限制,那么就是m^n 

AC代码: 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cstdio>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
const int mod=998244353;
ll n,m,k;
ll qmi(ll a,ll k){ll res=1;while(k){if(k&1) res=res*a%mod;a=a*a%mod;k>>=1;}return res;
}
void solve() {cin>>n>>m>>k;ll res;if(n==k) res=qmi(m%mod,n)%mod;//m范围过大,可达1e18,取个模防止快速幂时爆long longelse res=qmi(m%mod,n-k)%mod;//m可以取模是因为快速幂本就是乘法运算,乘法运算完全可以一边运算一边取模cout<<res<<endl;
}
int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t=1;cin>>t;while(t--)solve();return 0;
}

参考2023杭电暑假多校6 题解 1 2 6 10 | JorbanS_JorbanS的博客-CSDN博客

1002 Pair Sum and Perfect Square

树状数组

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<cstdio>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int N=1e5+10,M=450;
int p[N],pos[N];
int tr[N];
int sqr[M];
int n,q;
//树状数组
int lowbit(int x){return x & -x;
}
int sum(int x){int res=0;for(int i=x;i;i-=lowbit(i)) res+=tr[i];return res;
}
void add(int x,int c){for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
void solve() {cin>>n;memset(tr,0,sizeof tr);for(int i=1;i<=n;i++) cin>>p[i],pos[p[i]]=i;//pos记录值为p[i]的下标int m=0;for(int i=1;i*i<=2*n-1;i++) sqr[m++]=i*i;//将所有可能用到的平方数从小到大全部都记录在sqr数组中cin>>q;vector<vector<PII>>s(n+1);for(int i=0;i<q;i++){int l,r;cin>>l>>r;s[r].push_back({i,l});//右端点为r,然后将第几次询问的编号以及左端点放进去}int res=0;vector<int>ans(q+1);//枚举i从1到n,i作为右端点的编号for(int i=1;i<=n;i++){//从小到大枚举所有平方数,j为编号,sqr[j]即为平方数for(int j=0;j<m;j++){if(p[i]>=sqr[j]) continue;//如果p[i]已经大于等于该平方数了,那么说明该平方数太小了,那么就continue,继续枚举下一个平方数if(sqr[j]-p[i]>n) break;//sqr[j]即为平方数,p[i]即为右端点i的所对应的值,sqr[j]-p[i]即为左端点对应的值,如果大于n,说明该平方数太大了,那么直接break,后面平方数更大,就不用枚举了if(pos[sqr[j]-p[i]]<i) add(pos[sqr[j]-p[i]],1),res++;//如果左端点的下标小于右端点的下标i,那么就是可行的,那么以pos[sqr[j]-p[i]]为左端点的位置上个数+1,res记录有几对可行}//以i为右端点,枚举每一次询问的编号,以及询问区间[l,i],每一次遍历到的编号都是唯一的,res表示枚举到当前所有满足条件的对数,用res减去sum(l-1)算出的就是[l,i]区间里面所有满足条件的对数//首先右端点i是从小到大依次枚举的,然后前面的枚举过的右端点肯定是在i前面的,然后我们需要保证左端点要大于等于l,所以减去sum(l-1)即左端点小于等于l-1的满足条件的对数for(auto [id,l]:s[i]) ans[id]=res-sum(l-1);}for(int i=0;i<q;i++) cout<<ans[i]<<endl;
}
int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t=1;cin>>t;while(t--)solve();return 0;
}

1006 Perfect square number

法一:

将a[x]修改后区间和为平方数的个数=改之前区间和为平方数的个数-改之前含有x的区间和为平方数的区间个数+改之后含有x的区间和为平方数的区间个数

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<cstdio>
#define endl '\n'
using namespace std;
typedef long long ll;
const int N=310;
int a[N],s[N];
int n;
//判断x是否是平方数
bool check(int x) {if(pow((int)sqrt(x),2)==x) return true;return false;
}
void solve() {cin>>n;for(int i=1; i<=n; i++) {cin>>a[i];s[i]=s[i-1]+a[i];//前缀和}int res=0;int ans=0;//不重不漏地枚举区间for(int i=1; i<=n; i++) {for(int j=1; j<=i; j++) {if(check(s[i]-s[j-1])) ans++;//ans记录一共有几个区间的区间和为平方数,即记录修改前的个数}}res=ans;for(int x=1; x<=n; x++) {int suml=0;int sum=0;//记录含有x的区间和为平方数的区间个数int cnt[90000]= {0};for(int i=x; i>=1; i--) {suml+=a[i];int sumr=0;for(int j=x; j<=n; j++) {sumr+=a[j];int sumn=suml+sumr-2*a[x];//把x删掉后含有x的区间的区间和为sumnif(check(sumn+a[x])) sum++;//如果含有x的区间和为平方数,那么sum++cnt[sumn]++;//记录去掉x后区间和为sumn的个数}}int f[400]= {0}; //f[i]记录将a[x]修改为i之后含有x的区间和为平方数的区间个数for(int i=1; i<=300; i++) {int m=i*i;//枚举所有的平方数//将a[x]修改为m-jfor(int j=m; j>=0&&m-j<=300; j--) {f[m-j]+=cnt[j];}}for(int i=1; i<=300; i++) {res=max(res,ans-sum+f[i]);}}cout<<res<<endl;
}
int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t=1;cin>>t;while(t--)solve();return 0;
}

法二:

同样是将a[i]修改后区间和为平方数的个数=改之前区间和为平方数的个数-改之前含有i的区间和为平方数的区间个数+改之后含有i的区间和为平方数的区间个数

只不过预处理的方式不一样

 算改之前区间和为平方数的个数-改之前含有x的区间和为平方数的区间个数:

通过算区间和为平方数的区间个数前缀和以及区间和为平方数的区间个数后缀和,用数组x记录前缀和,用数组y记录后缀和,比如说我们要修改a[i],那么只要将x[i-1]和y[i+1]加起来即可,这样算出来的就是和i无关的区间和为平方数的区间个数,也就是改之前区间和为平方数的个数-改之前含有i的区间和为平方数的区间个数

接下来就只需要算改之后含有i的区间和为平方数的区间个数

for (int j = i; j <= n; j ++) pre(i, j, 1);
for(int j=1; j<=i-1; j++) pre(j,i-1,-1);

着重解释以上两句,我们想的是假设我们要修改第i个数,那么我们枚举与i有关的所有区间,即[i,i],[i,i+1],....[i,n]

以及[1,i],[2,i],...[i-1,i],但是由于我们枚举前面的i时,已经算过了,会导致重复,所以我们只要每次加上以i为左端点的区间就行,例如:

当i为1时,我们枚举以1为左端点的所有区间就已经是与1有关的所有区间了,如图,[1,1],[1,2],[1,3],[1,4],[1,5]

然后我们枚举以2为左端点的所有区间,如图,[2,2],[2,3],[2,4],[2,5],实际上呢,我们仍要枚举以2为右端点的所有区间,我们发现前面已经枚举过了,但是呢,我发现多了[1,1]这个与2无关的区间,所以我们要减去与2无关的区间,即[1,1]

 AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<cstdio>
#define endl '\n'
using namespace std;
typedef long long ll;
const int N=610,M=300;
int a[N],s[N];
int x[N],y[N];
int f[N];
int n;
//判断x是否是平方数
bool check(int x) {if(pow((int)sqrt(x),2)==x) return true;return false;
}
void pre(int l, int r, int k) {int sum = s[r] - s[l - 1];//i代表变化值,如果将i修改后,与i有关的区间和为平方数,那么就用数组f记录变化值(加一个M,使得原来从-300到300映射为0到600)的个数for (int i = -M; i <= M; i ++)if (check(sum + i)) f[i + M] += k;
}
void solve() {memset(x,0,sizeof x);memset(y,0,sizeof y);memset(f,0,sizeof f);cin>>n;for(int i=1; i<=n; i++) {cin>>a[i];s[i]=s[i-1]+a[i];//前缀和}//不重不漏地枚举区间for(int i=1; i<=n; i++) {for(int j=1; j<=i; j++) {if(check(s[i]-s[j-1])) x[i]++;//如果区间和为完全平方数,那么以i为右端点的区间和为平方数的区间个数+1}x[i]+=x[i-1];//跑一遍前缀和,数组x记录[1,i]中有多少个区间的区间和为平方数,即区间和为平方数的区间个数前缀和}for(int i=n; i>=1; i--) {for(int j=i; j<=n; j++) {if(check(s[j]-s[i-1])) y[i]++;//如果区间和为平方数,那么以i为左端点的区间和为平方数的区间个数+1}y[i]+=y[i+1];//跑一遍后缀和,数组y记录[i,n]中有多少个区间和为平方数,即区间和为平方数的区间个数后缀和}int res=0;for(int i=1; i<=n; i++) {for (int j = i; j <= n; j ++) pre(i, j, 1);for(int j=1; j<=i-1; j++) pre(j,i-1,-1);//以上两个循环是为了算修改第i个数后的与i有关的区间和为平方数的区间个数(假设f[关键字]=值,那么关键字放的是变化值的映射,值为个数)int now=0;for(int j=1; j<=M; j++) now=max(now,f[j-a[i]+M]);res=max(res,x[i-1]+y[i+1]+now);}cout<<res<<endl;
}
int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t=1;cin>>t;while(t--)solve();return 0;
}

1010 Caclulate

倍增的思想:任何一个十进制数都可以表示为若干个2的次幂的和

手上初始的数字为y,到点i,数字变为ki*y+bi,从点i到点j,数字变为ki*kj*y+kj*bi+bj

所以我们可以先预处理从每一个点走很多很多步的y前面的系数以及b(形式为k*y+b,我们需要预处理k以及b),由于走的步数是十进制数,而且可以达到很大,因为任意一个十进制数都可以由若干个2的次幂的和组成,所以对于每一个点,我们直接预处理从该点每次走2的次幂,那么最多走2的几次幂呢?由于最大到1e9,所以最多走2的30次幂

 

AC代码: 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<cstdio>
#define endl '\n'
//#define int long long
using namespace std;
const int mod=1e9+7;
const int N=1e5+10,M=31;
typedef long long ll;
int p[N][M];
ll k[N][M],b[N][M];
int n,q;
int query(){int x,l,y;cin>>x>>l>>y;x=p[x][0];//起点为x,先走一步//枚举2的次幂,比如4的二进制为100,然后和l进行与运算,如果l所对应的二进制的这一位也有1的话,那么该2的次幂就可以是l的一部分for(int i=0;i<M;i++){if((1<<i)&l){y=(y*k[x][i]+b[x][i])%mod;x=p[x][i];} }return y;
}
void solve() {cin>>n>>q;for(int i=1;i<=n;i++) cin>>k[i][0];for(int i=1;i<=n;i++) cin>>b[i][0];for(int i=1;i<=n;i++) cin>>p[i][0];for(int j=1;j<=30;j++){for(int i=1;i<=n;i++){p[i][j]=p[p[i][j-1]][j-1];//p[i][j]表示从位置i走2^j可以由位置i走2^(j-1)到达位置p[i][j-1],再从位置p[i][j-1]走2^(j-1)转移而来k[i][j]=k[i][j-1]*k[p[i][j-1]][j-1]%mod;//k[i][j]表示从点i开始包括i数4个数所对应的y前面的系数b[i][j]=(b[i][j-1]*k[p[i][j-1]][j-1]+b[p[i][j-1]][j-1])%mod;//b[i][j]同理,表示从点i开始包括i数4个数所对应的b}}while(q--) cout<<query()<<endl;
}
int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t=1;cin>>t;while(t--)solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/57576.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多通道振弦数据记录仪应用于桥梁监测

随着城市化进程的加快&#xff0c;城市桥梁的数量不断增加。对于城市交通的保障作用&#xff0c;桥梁的重要性不言而喻。而为了保障桥梁的安全&#xff0c;桥梁监测的重要性也越来越受到人们的重视。在桥梁监测中&#xff0c;多通道振弦数据记录仪的应用得到了广泛的认可和应用…

什么是芯片?

https://zhuanlan.zhihu.com/p/228757435?utm_sourceweibo&utm_mediumsocial&utm_oi895441374156029952&utm_contentsnapshot 什么是芯片&#xff1f; 半导体&#xff1a;一种材料&#xff0c;导电性能介于导体和半导体之间&#xff0c;比如硅、锗、砷化镓。用这…

JMeter命令行执行+生成HTML报告

1、为什么用命令行模式 使用GUI方式启动jmeter&#xff0c;运行线程较多的测试时&#xff0c;会造成内存和CPU的大量消耗&#xff0c;导致客户机卡死&#xff1b; 所以一般采用的方式是在GUI模式下调整测试脚本&#xff0c;再用命令行模式执行&#xff1b; 命令行方式支持在…

【车道线】TwinLiteNet 复现过程全纪录

码字不易&#xff0c;喜欢的请点赞收藏&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 论文全文翻译&#xff1a;【freespace】TwinLiteNet: An Efficient and Lightweight Model for Driveable Area and Lane Segmentation_莫克_Cheney的博客-CSDN博客 目录…

Keburnetes YAML配置文件管理

Kubernetes 支持 YAML 和 JSON 格式管理资源对象JSON 格式&#xff1a;主要用于 api 接口之间消息的传递YAML 格式&#xff1a;用于配置和管理&#xff0c;YAML 是一种简洁的非标记性语言&#xff0c;内容格式人性化&#xff0c;较易读 YAML 语法格式 大小写敏感使用缩进表示层…

【JavaEE进阶】Spring创建与使用

文章目录 一. 创建 Spring 项目1.1 创建一个Maven项目1.2 添加Spring依赖1.4. 创建一个启动类 二. 将 Bean 对象存放至 Spring 容器中三. 从 Spring 容器中读取到 Bean1. 得到Spring对象2. 通过Spring 对象getBean方法获取到 Bean对象【DI操作】 一. 创建 Spring 项目 接下来使…

【bug】记录一次使用Swiper插件时loop属性和slidersPerView属性冲突问题

简言 最近在vue3使用swiper时&#xff0c;突然发现loop属性和slides-per-view属性同时存在启用时&#xff0c;loop生效&#xff0c;下一步只能生效一次的bug&#xff0c;上一步却是好的。非常滴奇怪。 解决过程 分析属性是否使用错误。 loop是循环模式&#xff0c;布尔型。 …

etcd

文章目录 etcd单机安装设置键值对watch操作读取键过往版本的值压缩修订版本lease租约&#xff08;过期机制&#xff09;授予租约撤销租约keepAlive续约获取租约信息 事务基于etcd实现分布式锁原生实现官方 concurrency 包实现 服务注册与发现Go 操作 Etcd 参考 etcd etcd 是一…

一起来看看 Compose Accompanist

好久不见&#xff0c;真的挺久了&#xff0c;之前一个月写的文章比现在多半年的都多。今年第一篇文章是简单写了下 Android 14 的适配&#xff1a;Android 14 又来了&#xff1f;别扶&#xff01;抬起我来吧&#xff01; 今天咱们来一起看看 Compose Accompanist 吧&#xff0…

创意项目管理软件推荐:满足客户需求的完美解决方案

发现功能强大的工作管理软件&#xff0c;让创意大放异彩。将您团队的愿景变成引人注目的项目。 一、交付总是令人印象深刻的工作 Zoho Projects的创意项目管理软件可帮助您和您的团队在一个地方监督多个项目。使用我们的内置管理工具和模板&#xff0c;花更少的时间在管理上&a…

普及100Hz高刷+1ms响应 微星发布27寸显示器:仅售799元

不论办公还是游戏&#xff0c;高刷及低响应时间都很重要&#xff0c;微星现在推出了一款27寸显示器PRO MP273A&#xff0c; 售价只有799元&#xff0c;但支持100Hz高刷、1ms响应时间&#xff0c;还有FreeSync技术减少撕裂。 PRO MP273A的100Hz高刷新率是其最大的卖点之一&#…

[每周一更]-(第57期):用Docker、Docker-compose部署一个完整的前后端go+vue分离项目

文章目录 1.参考项目2.技能点3.GO的Dockerfile配置后端的结构如图Dockerfile先手动docker调试服务是否可以启动报错 4.Vue的Dockerfile配置前端的结构如图nginx_docker.confDockerfile构建 5.docker-compose 整合前后端docker-compose.yml错误记录&#xff08;1&#xff09;ip端…