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

news2024/11/14 18:48:29

1001 Typhoon

计算几何

对于每一个避难点,计算其到所有线段的距离,取min即可

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<deque>
#include<cmath>
#include<cstdio>
#include<iomanip>
#define endl '\n'
#define eps 1e-9
//#define int long long
using namespace std;
typedef long long ll;
const int N=1e4+10,inf=2e9;
double dist[N];
//向量表示(定义一个结构体,用坐标表示向量)
struct Point {
    double x,y;
    double len() const { //模
        return sqrt(x*x+y*y);
    }
};
Point operator+(Point a,Point b) { //加法
    return {a.x+b.x,a.y+b.y};
}
Point operator-(Point a,Point b) { //减法
    return {a.x-b.x,a.y-b.y};
}
double operator&(Point a,Point b) { //点积
    return a.x*b.x+a.y*b.y;
}
double operator*(Point a,Point b) { //叉积
    return a.x*b.y-a.y*b.x;
}
//向量的点积
double dot(Point a,Point b,Point c) {
    return (b-a)&(c-a);//a,b,c均为点,向量b-a与向量c-a进行点积
}
//向量的叉积
double cross(Point a,Point b,Point c) {
    return (b-a)*(c-a);
}
int n,m;
void solve() {
    cin>>m>>n;
    vector<Point>p(m);
    for(int i=0; i<m; i++) cin>>p[i].x>>p[i].y;
    vector<Point>s(n);
    for(int i=0; i<n; i++) cin>>s[i].x>>s[i].y;
    vector<double>dis(n,inf);//定义了一个名为dis的变量,它是一个长度为n的vector容器,其中每个元素的初始值都被设置为inf
    for(int i=1; i<m; i++) {
        //枚举线段(用向量表示)
        Point a=p[i-1],b=p[i];
        //枚举避难所
        for(int j=0; j<n; j++) {
            Point c=s[j];
            double d1=dot(a,b,c);//求向量b-a与向量c-a的点积
            double d2=dot(b,a,c);//求向量c-b与向量c-a的点积
            double res;
            if(d1<0||d2<0) {
                res=min((c-a).len(),(c-b).len());//点积小于0说明角度是钝角,那么垂足就在线段外,取两点最小值
            } else {
                res=cross(a,b,c)/(b-a).len();//求点到线段的垂直距离,为向量b-a与向量c-a叉积再除以向量b-a的模(面积/底)
            }
            res=fabs(res);
            if(res<eps) res=0;//如果答案小于精度,则直接相当于等于0
            dis[j]=min(dis[j],res);
        }
    }
    cout<<setiosflags(ios::fixed)<<setprecision(4);//保留四位小数,四舍五入,头文件为#include<iomanip>
    for(int i=0; i<n; i++) cout<<dis[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 Touhou Red Red Blue

法一(dp):

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cstdio>
#define endl '\n'
#define get(a,b) (a*4+b)
//#define int long long
using namespace std;
typedef long long ll;
const int N=1e5+10,M=16;
int f[N][M];//f[i][j]表示当前球为i,两个袋子的球的状态为j的最大得分,袋子1中的球有4种状态,袋子2中的球也有4种状态,一共4*4=16种状态(0代表没有球,1~3代表球的颜色为R,G,B)
void solve() {
    string s;
    cin>>s;
    int n=s.size();
    for(int i=1; i<=n; i++) {
        int c;//表示当前球的颜色,1代表R,2代表G,3代表B
        if(s[i-1]=='R') c=1;
        else if(s[i-1]=='G') c=2;
        else c=3;
        for(int j=0; j<M; j++) f[i][j]=f[i-1][j]; //可以选择存储或放弃UFO,我们选择扔掉它
        //枚举1号袋子的状态和2号袋子的状态,0代表没有球,1~3代表分别代表球的颜色为R,G,B
        for(int a=0; a<=3; a++) {
            for(int b=0; b<=3; b++) {
                //如果两个袋子都不为空
                if(a&&b) {
                    //如果3个球的颜色均相同,那么三个球都消掉,得1分,和消消乐一样
                    if(a==b&&b==c) {
                        //得到一个附加的球放在袋子1里,此时袋子2为空
                        for(int d=1; d<=3; d++) f[i][4*d]=max(f[i][4*d],f[i-1][get(a,b)]+1);
                    }
                    //如果三个球的颜色均不相同,那么3个球都会消失然后会得到两个附加的球,放到袋子1和袋子2中
                    else if(a&&b&&a!=b&&a!=c&&b!=c) {
                        //枚举袋子1的球的颜色
                        for(int d=1; d<=3; d++) {
                            //枚举袋子2的球的颜色
                            for(int e=1; e<=3; e++) {
                                f[i][get(d,e)]=max(f[i][get(d,e)],f[i-1][get(a,b)]);
                            }
                        }
                    }
                    //否则,扔掉袋子1中的球,将袋子2中的球移到袋子1中,并将当前球放到袋子2中
                    else f[i][get(b,c)]=max(f[i][get(b,c)],f[i-1][get(a,b)]);
                }
                //if(a&&b)不满足,说明其中一个袋子是空的,
                //如果a不空,b空,那么就把c放到第二个袋子里
                else if(a) f[i][get(a, c)] = max(f[i][get(a, c)], f[i - 1][get(a, b)]);
                //如果a,b袋子均为空,那么就把c放到第一个袋子里
                else f[i][get(c, 0)] = max(f[i][get(c, 0)], f[i - 1][get(a, b)]);
            }
        }
    }
    int res=0;
    for(int i=0; i<M; i++) res=max(res,f[n][i]);
    cout<<res<<endl;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    memset(f[0],-0x3f,sizeof f[0]);//初始化为负无穷,因为后面要取max
    f[0][0]=0;//初始状态得分为0,由此开始递推
    int t=1;
    cin>>t;
    while(t--)
        solve();
    return 0;
}

法二(贪心):

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;
void solve() {
    string s;
    cin>>s;
    int n=s.size();
    int r=0,g=0,b=0;
    int res=0;
    int t=0;//表示这一轮可以自己选几个球,初始为0
    for(int i=0;i<n;){
        //这轮可以自选一个球放在袋子1中,然后看后面两个球颜色是否相同
        if(t==1){
            if(i==n-1) break;//自选的1个球加上最后一个球一共也才2个球,不足三个球是不能消消乐的,不可以得分了,直接跳出
            if(s[i]==s[i+1]) t=1,res++;//,如果后两个球颜色相同,那么将这个自选的球颜色变得和后两个球颜色一样,使得三个消消乐消掉,+1分,下一轮进入t=1的状态,即下一轮可以自选一个球放到袋子1中
            else t=2;//如果后两个球颜色不相同,那么就使得三个球颜色均不相同,下一轮进入t=2的状态,即下一轮可以自选2个球分别放到袋子1和袋子2中
            i+=2;//跳过本次和下一次,因为连续三个球都消失了
        }
        //这轮可以自选两个球放在袋子1和袋子2中,我们完全可以使得这两个球和当前球颜色相同,然后消消乐消掉这三个球,+1分,下一轮
        else if(t==2){
            t=1;//凑成3个颜色相同的球,消消乐,下一轮进入t=1的状态
            res++;
            i++;//跳过本此
        }
        //只有初始状态为t=0,然后接下来就是在t=1和t=2两状态之间转来转去
        else{
            if(s[i]=='R') r++;
            else if(s[i]=='G') g++;
            else b++;
            if(r&&g&&b) t=2;//如果三种颜色的球的数量都不为0,那么说明三个球颜色均不相同,那么进入t=2的状态,下一轮可以自选两个球
            else if(r==3||b==3||g==3) t=1,res++;//如果三个球颜色均相同,那么消消乐,+1分,进入t=1的状态,下一轮可以自选一个球
            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;
}

1007 Expectation(Easy Version)

算期望

根据样例:

一共有n局比赛

通项=组合数(n局中赢哪x局)*n局赢x局的概率*(1^m+2^m+...x^m)

然后遍历1到n,将其全部加起来

也就是:

假设赢一局的概率为p

C(n,1)*p^1*(1-p)^(n-1)*1^m+C(n,2)*p^2*(1-p)^(n-2)*(1^m+2^m)+...C(n,n)*p^n*(1^m+2^m+...+n^m)

由此,我们可以将其分为三个部分A,B以及C

然后呢,每一部分我们都可以不断地累加或者累乘

我们可以发现组合数每次都可以在上一项C(n,i)的基础上乘(n-i)/(i+1)

对于概率这一部分也是同样如此:

再次转换: 

发现每次都是乘a*(b-a)^(-1)

分母始终都是b^n,所以先不用管分母,只需要当全部算完之后,最后除以一个b^n就行了

最后一部分相比之下就很简单,直接加(i+1)^m

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<deque>
#include<cmath>
#include<cstdio>
#define endl '\n'
#define int long long
using namespace std;
typedef long long ll;
const int mod=998244353;
int n,m,a,b;
inline int qmi(int a,int k){
    int res=1;
    while(k){
        if(k&1) res=(ll)res*a%mod;
        a=(ll)a*a%mod;
        k>>=1;
    }
    return res;
}
inline int inv(int x){
    return qmi(x,mod-2);
}
int solve() {
    cin>>n>>m>>a>>b;
    int res=0;
    int k=a*inv(b-a)%mod;
    int A=n%mod,B=qmi(b-a,n-1)*a%mod,C=1;
    for(int i=1;i<=n;i++){
        (res+=A*B%mod*C%mod)%=mod;
        A=A*(n-i)%mod*inv(i+1)%mod;
        (B*=k)%=mod;
        (C+=qmi(i+1,m))%=mod;
    }
    return (res*inv(qmi(b,n)))%mod;
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    while(t--)
    cout<<solve()<<endl;
    return 0;
}

1012 Counting Stars 

如图,比如说想要求以1为顶点的2-star图的数量,发现顶点1有三条边,那么就是在三条边中选择两条边的方案数,这样就用到了组合数学

原本我想的是分别求每一个cnt[i],对于每一个cnt[i],枚举所有的顶点,将每个顶点所形成的i-star图的个数加起来,但是会发现这样双重循环就超时了

for (int i = 2; i <= n - 1; i++) {
        for (int j = 1; j <= n; j++) {
            (cnt[i] += c[e[j].size()][i]) %= mod;
        }
    }

可以换一种思路:枚举所有的顶点,然后我们知道该顶点的度数,就是每枚举一个顶点,就记录以该顶点可以形成的2-star,3-star...的数量,这样做的好处是不会超时,因为根据握手定理

握手定理:

所以度数之和为2*m,为2e6,也就是说时间复杂度不会超过2e6 

    for(int i=1;i<=n;i++){
        for(int j=2;j<=d[i];j++){
            (ans[j]+=C(deg[i],j))%=mod;
        }
    }

 可以这样理解,加一个cnt++,然后cnt加的次数不会超过2e6

for(int i=1;i<=n;i++){
        for(int j=2;j<=d[i];j++){
            (ans[j]+=C(deg[i],j))%=mod,cnt++;
        }
    }

现在主要就是求组合数的问题,因为n太大了,所以求组合数不好求

我们发现C(n,1)=n/1,C(n,2)=n*(n-1)/(1*2),C(n,3)=n*(n-1)/(1*2*3)

所以我们可以先预处理阶乘以及阶乘的逆元

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<deque>
#include<cmath>
#include<cstdio>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll;
const int N=1e6+10,mod=1e9+7;
int d[N];
int fac[N],ifac[N];
int ans[N];
int n,m;
//快速幂
int qmi(int a,int k){
    int res=1;
    while(k){
        if(k&1) res=(ll)res*a%mod;
        a=(ll)a*a%mod;
        k>>=1;
    }
    return res;
}
//求组合数
int C(int n,int m){
    if(n<m) return 0;
    return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
void solve() {
    cin>>n>>m;
    for(int i=1;i<=n;i++) d[i]=ans[i]=0;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        d[u]++,d[v]++;
    }
    for(int i=1;i<=n;i++){
        for(int j=2;j<=d[i];j++){
            (ans[j]+=C(d[i],j))%=mod;
        }
    }
    int res=0;
    for(int i=2;i<=n-1;i++) res^=ans[i];
    cout<<res<<endl;
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //预处理阶乘以及阶乘的逆元
    fac[0]=ifac[0]=1;//0的阶乘是1,0的阶乘的逆元也是1
    for(int i=1;i<N;i++) fac[i]=1ll*fac[i-1]*i%mod;//预处理阶乘
    ifac[N-1]=qmi(fac[N-1],mod-2);//先求出fac[N-1]的逆元,由于(n+1)!=n!*(n+1)==>n!^(-1)=(n+1)!^(-1)*(n+1),所以也可以通过递推得到阶乘的逆元
    for(int i=N-2;i>=1;i--) ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
    int t=1;
    cin>>t;
    while(t--)
    solve();
    return 0;
}

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

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

相关文章

【云原生】K8S二进制搭建二:部署CNI网络组件

目录 一、K8S提供三大接口1.1容器运行时接口CRI1.2云原生网络接口CNI1.3云原生存储接口CSI 二、Flannel网络插件2.1K8S中Pod网络通信2.2Overlay Network2.3VXLAN2.4Flannel 三、Flannel udp 模式的工作原理3.1ETCD 之 Flannel 提供说明 四、vxlan 模式4.1Flannel vxlan 模式的工…

Packet Tracer - 配置初始路由器设置

Packet Tracer - 配置初始路由器设置 目标 第 1 部分&#xff1a;检验默认路由器配置 第 2 部分&#xff1a;配置并检验初始路由器配置 第 3 部分&#xff1a;保存运行配置文件 拓扑图 背景信息 在本练习中&#xff0c;您将执行基本的路由器配置。您将使用加密密码和明文…

HDFS架构刨析

HDFS架构刨析 概述HDFS架构图整体概述主角色&#xff1a;namenodefsimage内存元数据镜像文件edits log&#xff08;Journal&#xff09;编辑日志 从角色&#xff1a;datanode主角色辅助角色&#xff1a;secondarynamenode 重要特性主从架构分块存储机制副本机制namespace元数据…

京津冀特大暴雨,带给应急通信工作怎样的启示?

上个月&#xff0c;我发卫星基站中移集采那篇文章的时候&#xff0c;就提到&#xff1a;未来即将进入汛期&#xff0c;应急通信装备将发挥重要作用。 果不其然&#xff0c;没多久&#xff0c;超强台风“杜苏芮”形成并登陆福建&#xff0c;造成巨大破坏。 除了在南方地区的肆虐…

Java工程师研学之路【003Java基础语法下】

知识体系 挑战&#xff08;challenge&#xff09; 从终端输入字符串(输入的个数不超过10个)&#xff0c;当输入遇到end字符串时&#xff0c;结束输入并且打印出之前输入的所有字符串。 思路&#xff1a;首先要输出end之前的所有字符串&#xff0c;故可以使用数组把输入的字符…

zookeeper+kafka分布式消息队列集群的部署

目录 一、zookeeper 1.Zookeeper 定义 2.Zookeeper 工作机制 3.Zookeeper 特点 4.Zookeeper 数据结构 5.Zookeeper 应用场景 &#xff08;1&#xff09;统一命名服务 &#xff08;2&#xff09;统一配置管理 &#xff08;3&#xff09;统一集群管理 &#xff08;4&…

零代码爬虫平台SpiderFlow的安装

什么是 Spider Flow &#xff1f; Spider Flow 是一个高度灵活可配置的爬虫平台&#xff0c;用户无需编写代码&#xff0c;以流程图的方式&#xff0c;即可实现爬虫。该工具支持多数据源、自动保存至数据库、任务监控、抓取 JS 动态渲染页面、插件扩展&#xff08;OCR 识别、邮…

17、YML配置文件及让springboot启动时加载我们自定义的yml配置文件的几种方式

YML配置文件及加载自定义配置文件的几种方式 ★ YAML配置文件 其实本质和.properties文件的是一样的。 Spring Boot默认使用SnakeYml工具来处理YAML配置文件&#xff0c;SnakeYml工具默认就会被spring-boot-starter导入&#xff0c;因此无需开发者做任何额外配置。 YAML本质…

为Android构建现代应用——应用导航设计

在前一章节的实现中&#xff0c;Skeleton: Main structure&#xff0c;我们留下了几个 Jetpack 架构组件&#xff0c;这些组件将在本章中使用&#xff0c;例如 Composables、ViewModels、Navigation 和 Hilt。此外&#xff0c;我们还通过 Scaffold 集成了 TopAppBar 和 BottomA…

论文阅读- Uncovering Coordinated Networks on Social Media:Methods and Case Studies

链接&#xff1a;https://arxiv.org/pdf/2001.05658.pdf 目录 摘要&#xff1a; 引言 Methods Case Study 1: Account Handle Sharing Coordination Detection 分析 Case Study 2: Image Coordination Coordination Detection Analysis Case Study 3: Hashtag Sequen…

Leetcode-每日一题【剑指 Offer 39. 数组中出现次数超过一半的数字】

题目 数组中有一个数字出现的次数超过数组长度的一半&#xff0c;请找出这个数字。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]输出: 2 限制&#xff1a; 1 < 数组长度 < 50000 解题思路 前置知…

手把手教新手最新Maven3.9.3下载安装配置

当前文档地址&#xff1a;有道云笔记 手把手教新手最新Maven3.9.3下载安装配置 1.下载 Maven官网&#xff1a;Maven – Maven Documentation 1.1打开主页&#xff0c;点击 Download 1.2 选择二进制压缩包&#xff0c;点击apache-maven-3.9.3-bin.zip进行下载 1.3 选择合适的…

租赁类小程序定制开发|租赁管理系统源码|免押租赁系统开发

随着互联网的发展&#xff0c;小程序成为了一种重要的移动应用开发方式。租赁小程序作为其中的一种类型&#xff0c;可以为很多行业提供便利和创新。下面我们将介绍一些适合开发租赁小程序的行业。   房屋租赁行业&#xff1a;租房小程序可以帮助房东和租户快速找到合适的租赁…

史上最全docker启动命令

docker Docker 启动镜像 一、查看当前docker中下载的镜像&#xff0c;如下图&#xff0c;当前我的Docker容器中存在两个镜像 &#xff0c;tomcat、mysql 二、启动镜像 (因启动命令参数过多&#xff0c;同时各种镜像启动时可以增加额外的参数&#xff0c;本次以启动mysql5.6为例…

Manage repositories按钮没有找到

今天安装PyCharm 2022.2.5版本没有发现Manage Repositories&#xff0c;如下图&#xff1a; 解决办法&#xff1a; 第一步&#xff1a;打开pycharm 根据图示按顺序点击底部内容 第二步 &#xff1a;点击加号&#xff0c;添加国内镜像源即可 第三步&#xff1a;国内镜像源地址 …

SpringBoot之Actuator基本使用

SpringBoot之Actuator基本使用 引入分类常用接口含义healthbeansconditionsheapdumpmappingsthreaddumploggersmetrics 引入 <!-- actuator start--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter…

【C++入门到精通】C++入门 —— string类(STL)

目录 一、STL简介 1.STL是什么 2.STL的内容 3.STL的使用前提 二、string类 1.string类 是什么 2.string类的特点和操做 ⭕构造和初始化 ⭕字符串大小和容量 ⭕字符访问和修改 ⭕字符串连接和拼接 ⭕子串操作 ⭕字符串比较 ⭕字符串修改 ⭕获取字符的ASCII码 ⭕…

音频光耦合器

音频光耦合器是一种能够将电信号转换为光信号并进行传输的设备。它通常由发光二极管&#xff08;LED&#xff09;和光敏电阻&#xff08;光电二极管或光敏电阻器&#xff09;组成。 在音频光耦合器中&#xff0c;音频信号经过放大和调节后&#xff0c;被转换为电流信号&#xf…

RISCV 5 RISC-V调用规则

RISCV 5 RISC-V调用规则 1 Register Convention1.1 Integer Register Convention1.2 Floating-point Register Convention 2. Procedure Calling Convention2.1 Integer Calling Convention2.2 Hardware Floating-point Calling Convention2.3 ILP32E Calling Convention2.4 Na…

web前端转正工作总结范文5篇

web前端转正工作总结&#xff08;篇1&#xff09; 来到__有限公司已经三个月了&#xff0c;目前的工作是前端开发&#xff0c;我是一名应届毕业生&#xff0c;之前没有过工作经验&#xff0c;在刚来到__这个大家庭的时候&#xff0c;我就被这里的工作气氛深深地吸引&#xff0…