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

news2024/11/26 7:35:26

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 long
    else 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的区间的区间和为sumn
                if(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-j
            for(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.coloradmin.cn/o/848015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3 大屏数字滚动效果

父组件&#xff1a; <template> <div class"homePage"> <NumRoll v-for"(v, i) in numberList" :key"i" :number"v"></NumRoll> </div> </template> <script setup> import { onMounted, r…

【Vue3】动态组件

动态组件的基本使用 动态组件&#xff08;Dynamic Components&#xff09;是一种在 Vue 中根据条件或用户输入来动态渲染不同组件的技术。 在 Vue 中使用动态组件&#xff0c;可以使用 元素&#xff0c;并通过 is 特性绑定一个组件的名称或组件对象。通过在父组件中改变 is 特…

C++ 虚析构函数

在C中&#xff0c;不能声明虚构造函数&#xff0c;但是可以声明虚析构函数。 析构函数没有类型&#xff0c;也没有参数&#xff0c;和普通成员函数相比&#xff0c;虚析构函数情况很简单。 虚析构函数的声明语法&#xff1a; virtual ~类名();如果一个类的析构函数是虚函数&…

Python自动化测试用例:如何优雅的完成Json格式数据断言

目录 前言 直接使用 优化 封装 小结 进阶 总结 资料获取方法 前言 记录Json断言在工作中的应用进阶。 直接使用 很早以前写过一篇博客&#xff0c;记录当时获取一个多级json中指定key的数据&#xff1a; #! /usr/bin/python # coding:utf-8 """ aut…

森海塞尔为 CUPRA 首款纯电轿跑 SUV – CUPRA Tavascan 注入音频魅力

森海塞尔为 CUPRA 首款纯电轿跑 SUV – CUPRA Tavascan 注入音频魅力 音频专家森海塞尔携手富有挑战精神的 CUPRA&#xff0c;雕琢时代新贵车型&#xff0c;打造畅快尽兴的驾驶体验 全球知名音频专家森海塞尔与以颠覆传统、充满激情、不甘现状而闻名的汽车品牌 CUPRA 展开合作…

awk案例练习

目录 一、awk练习 1.1筛选ip地址 1.2字段去重 1.3次数统计 1.4统计TCP连接状态 1.5处理字段缺失的数据 1.6筛选给定时间范围内的日志 一、awk练习 1.1筛选ip地址 ifconfig命令查看IP 利用awk进行筛选 ifconfig | awk BEGIN{RS""}NR2{print $6} RS指定输入记…

找工作的才是大爷?面试了一个工作4年的测试工程师,一问连自动化基础都不清楚,还反过来怼我....

我们公司也开始大量招人了&#xff0c;我这次是公司招聘的面试官之一&#xff0c;主要负责一些技术上的考核&#xff0c;这段时间还真让我碰到了不少奇葩求职者 昨天公司的HR小席刚跟我吐槽&#xff1a;这几个星期没有哪天不加班的&#xff01;各种招聘网站上的消息源源不断&a…

干货分享 | TSMaster图形模块功能详解(三)—— 以CAN信号为例

TSMaster图形模块功能详解第二章节中&#xff0c;我们主要分享了显示模式、图形设置、信号跳转与波形窗口移动、信号波形缩放4大模块的操作教程。 本章节在上一篇基础上&#xff0c;继续介绍TSMaster图形模块功能第11-15模块的教程。 本文目录&#xff1a; 11、适配 11.1 水平…

基于JavaWeb的家居电子商城管理系统

家居电子商城HOMEECMS 大二下的JavaWeb小学期课程写的一个家居电子商城管理系统&#xff0c;没有spring框架&#xff0c;纯servlet&#xff0c;线上家居电子商城系统&#xff0c;主要实现了用户注册&#xff0c;登录、浏览&#xff0c;查看家居商品信息&#xff0c;购物车&…

元宇宙3D数字虚拟客服打造年轻化、数字化营销新品牌

融合了元宇宙、AI和云计算等技术的虚拟数字人&#xff0c;成为元宇宙数字内容交互的载体&#xff0c;将现实世界中的人与虚拟数字世界的场景、模型及产品链接起来&#xff0c;特别是为电力企业打造的电力元宇宙平台&#xff0c;带来营销宣传多重好处的同时&#xff0c;树立了数…

什么?200?跨域?

情景复现 今天我遇到了一件很奇怪的事情就是&#xff0c;当我请求后端网关&#xff0c;然后通过网关去请求相应的服务&#xff0c;都进行了跨域处理 但是&#xff0c;奇怪的是我在请求的时候&#xff0c;回来的响应码是200&#xff0c;但是报错了&#xff0c;报的还是200的同…

基于微服务架构的智慧工地云平台系统源码

Spring Cloud 智慧工地源码&#xff0c;智慧建造源码 系统概述&#xff1a; 智慧工地云平台系统&#xff0c;依托计算机技术、物联网、云计算、大数据、人工智能、VR&AR等技术相结合&#xff0c;对建筑工地中的管理人员、施工人员、车辆/物料、施工设备、视频监控等数据有…

模仿火星科技 基于cesium+角度测量+高度测量+可编辑

1. 创建提示窗&#xff1a; 启动Cesium应用&#xff0c;地图场景将打开&#xff0c;欢迎您进入编辑模式。 在屏幕的一角&#xff0c;一个友好的提示窗将呈现&#xff0c;随着您的操作&#xff0c;它会为您提供有用的信息和指导。 2. 绘制面积&#xff1a; 轻轻点击鼠标左键&a…

华为OD机试真题 Java 实现【疫情扩散时间计算】【2023 B卷 200分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

【Python学习笔记】Matplotlib画图

Matplotlib画图 一、基本函数1. plt.plot2. plt.text3. 设置刻度4. 设置坐标5.设置网格 二、绘制折线图三、绘制散点图四、绘制柱状图五、绘制双坐标图 一、基本函数 1. plt.plot 参数功能选项color改变折线颜色‘r’,‘g’,‘b’,‘black’,‘gray’marker改变数据点的形状‘…

固态硬盘 vs 机械硬盘:选择合适的存储方案

随着计算机的快速发展&#xff0c;各种硬件组件如CPU、显卡以及制作工艺都取得了长足的进步&#xff0c;但是磁盘的发展相对较为缓慢&#xff0c;这也导致了磁盘性能在一定程度上限制了计算机的整体性能。为了解决这个问题&#xff0c;固态硬盘应运而生。 那么&#xff0c;我们…

(亲测)制作linux启动U盘

下载软碟通 https://cn.ultraiso.net/xiazai.html 点击文件中的打开&#xff0c;选中Linux系统 插入U盘&#xff0c;点击启动中的写入硬盘映像 点击之后会自动选中U盘。界面如下&#xff1a; 点击写入&#xff0c;点击后U盘会格式化&#xff0c;所以U盘里面有重要东西的话…

中国金融四十人论坛:2023年第二季度宏观政策报告(附下载)

关于报告的所有内容&#xff0c;公众【营销人星球】获取下载查看 核心观点 • 运行环境&#xff1a;外部环境方面&#xff0c;全球经济景气回落&#xff0c;会酸交作仍在收秀。内部环演方百&#xff0c;公共支出进一步旅爱&#xff0c;真交利本显考上开&#xff0c;社酸塔这创…

neo4j终端操作

1】进入容器 (base) xiaokkkxiaokkkdeMacBook-Pro ~ % docker exec -it 77ed5fe2b52e /bin/bash 2】启动、停止neo4j root77ed5fe2b52e:/var/lib/neo4j/bin# ./neo4j start Neo4j is already running (pid:7). Run with --verbose for a more detailed error message.root7…

项目实战 — 消息队列(6){内存数据管理}

目录 一、设计数据结构 二 、实现管理方法 &#x1f345; 1、实现交换机管理 &#x1f345; 2、实现队列管理 &#x1f345; 3、实现绑定管理 &#x1f388;插入绑定操作 &#x1f388;删除绑定 &#x1f345; 4、进行消息管理 &#x1f345; 5、发送消息到指定队列 &a…