19级个人训练赛0010-赛后总结及反思

本文精选了六道算法竞赛题目,包括唯一分解定理、组合数+错排、矩阵快速幂、嵌套循环组合数、平均数方差优化及金牌难题,详细解析了每道题目的解题思路和代码实现,覆盖了从数据结构到复杂算法的多种技术。

A-LightOJ - 1035
唯一分解定理问题,将给定的n for一遍,每个数进行分解,最后输出即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <functional>
#include <vector>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn=3e5+50;
const int inf=1e9;
const int MOD=1e9+7;
const int p=1e9+6;

int pri[100]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
//给定数据范围小,打表就行
int num[107];

void init(int n)
{
    for(int i=1;n>=pri[i]&&i<=25;i++)//开始没写i<=25 RE了一次
    {
        while(n%pri[i]==0)
        {
            num[pri[i]]++;
            n/=pri[i];
        }
    }
    if(n>0) num[n]++;
}

int main()
{
    int t;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        int n;
        scanf("%d",&n);
        memset(num,0,sizeof(num));
        for(int i=2;i<=n;i++)
        {
            init(i);
        }
        int sign=0;
        for(int i=1;i<=25;i++)
            if(num[pri[i]]!=0) sign++;
        int sign1=1;
        printf("Case %d: %d = ",ca,n);
        for(int i=1;i<=25;i++)
        {
            if(num[pri[i]]!=0&&sign!=sign1) {printf("%d (%d) * ",pri[i],num[pri[i]]);sign1++;}
            else if(num[pri[i]]!=0&&sign==sign1) printf("%d (%d)\n",pri[i],num[pri[i]]);
        }
    }
    return 0;
}

B-HDU-2049
组合数+错排

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <functional>
#include <vector>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn=3e5+50;
const int inf=1e9;
const int MOD=1e9+7;
const int p=1e9+6;

int num[107];

ll quick_pow(ll n,ll m)
{
    ll base=n%MOD;
    ll ans=1;
    while(m>0)
    {
        if(m&1) ans=ans*base%MOD;
        base=base*base%MOD;
        m>>=1;
    }
    return ans;
}

ll C(int n,int m)
{
    n=min(n,m-n);
    int ans=1;
    for(int i=1;i<=n;i++)
        ans=ans*(m-n+i)*quick_pow(i,MOD-2)%MOD;
    return ans;
}
ll D(int n)
{
    if(n==2) return 1;
    if(n==1) return 0;//这里板子背错了,开始写的if(n==2||n==1) return 1;直接给我WA了
    return (n-1)*(D(n-1)+D(n-2));
}

int main()
{
    int t;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        printf("%lld\n",C(m,n)*D(m));

    }
    return 0;
}

C-HDU-6470
矩阵快速幂问题
由题意求出递推公式 f(n)=f(n-2)×2+f(n-1)+n³,并构建转移状态矩阵
比赛的时候很早就构造出来了,也很早就完成了代码整体的输入,但是死活过不了样例,第一个都过不去。。。
然后一直debug到比赛结束,之后继续de,最后终于发现是矩阵乘法写反了Orz
A×B≠B×A
不要太绝望

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <functional>
#include <vector>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn=3e5+50;
const int inf=1e9;
const int MOD=123456789;
const int p=1e9+6;

struct node
{
    ll a[10][10];
};

node operator*(node x,node y)
{
    node tmp;
    for(int i=1;i<=6;i++)
     for(int j=1;j<=6;j++)
     {
        tmp.a[i][j]=0;
        for(int k=1;k<=6;k++)
     {
         tmp.a[i][j]+=x.a[i][k]*y.a[k][j]%MOD;
         tmp.a[i][j]%=MOD;
     }
     }
    return tmp;
}

node operator^(node x,ll b)
{
    node tmp;
    memset(tmp.a,0,sizeof(tmp.a));
    for(int i=1;i<=6;i++)
        tmp.a[i][i]=1;
    while(b>0)
    {
        if(b&1) tmp=tmp*x;
        x=x*x;
        b>>=1;
    }
    return tmp;
}

int main()
{
    node zhuanyi;
    node chushi;
    int t;
    scanf("%d",&t);
    memset(zhuanyi.a,0,sizeof(zhuanyi.a));
    memset(chushi.a,0,sizeof(chushi.a));
    zhuanyi.a[1][1]=zhuanyi.a[2][1]=zhuanyi.a[3][3]=zhuanyi.a[4][4]=zhuanyi.a[5][5]=zhuanyi.a[6][6]=zhuanyi.a[1][3]=zhuanyi.a[1][6]=zhuanyi.a[3][6]=zhuanyi.a[4][6]=zhuanyi.a[5][6]=1;
    zhuanyi.a[1][2]=zhuanyi.a[4][5]=2;
    zhuanyi.a[1][4]=zhuanyi.a[3][4]=zhuanyi.a[3][5]=zhuanyi.a[1][5]=3;
    chushi.a[1][1]=2,chushi.a[2][1]=1,chushi.a[3][1]=8,chushi.a[4][1]=4,chushi.a[5][1]=2,chushi.a[6][1]=1;
    while(t--)
    {
        ll n;
        scanf("%lld",&n);
        node tmp;
        int tt;
        tt=1;
        tmp=(zhuanyi^(n-2))*chushi;//就是这里写反了 死活没忘这个方向想QAQ
        printf("%d\n",tmp.a[1][1]);
    return 0;
}

转移态矩阵的构造我是之前看大佬的博客学会的
这里附上链接

D-HDU-1799
比赛的时候没看懂题
嵌套m层循环,问最后操作次数是多少
其实就是求组合数
因为模数较小,不能使用逆元处理
根据公式C(n,m) = C(n - 1,m) + C(n - 1,m - 1)打表处理

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <functional>
#include <vector>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn=3e5+50;
const int inf=1e9;
const int MOD=1007;
const int p=1e9+6;

int C[2007][2007];

void init()
{
    C[0][0]=1;
    for(int i=1;i<=2000;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=2000;j++)
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
    }
}

int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int m,n;
        scanf("%d%d",&n,&m);
        printf("%d\n",C[m][n]);
    }
    return 0;
}

E-CFgym
平均数是固定的

学长给的标程

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll mod = 1000000007;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;

double a[maxn];
struct node {
    int id;//锅的序号
    double y;//当前分锅人数下的方差-再加入一个人分锅的方差,具体推导见最下方
    int cnt;//计数,一个问题几个人背锅
    bool friend operator<(node a, node b) {//用来维护优先队列,队列顶端是y的最大值,此时对队列顶端处理可以让方差减小的值最大,即每个人的贡献最大
        return a.y < b.y;
    }
};
priority_queue<node> q;
int main() {
    int t, n, m;
    scanf("%d", &t);
    for (int cas = 1; cas <= t; cas++) {
        scanf("%d%d", &n, &m);
        double av = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%lf", &a[i]);
            av += a[i];//求锅的和
            q.push({i, a[i] * a[i] - a[i] * a[i] / 2, 1});//中间的式子可以写成a[i]*a[i]*(1.0/1-1.0/2)
        }
        av /= m;//锅分给每个人的平均值
        for (int i = 1; i <= m - n; i++) {
            node tmp = q.top(), tt;
            q.pop();
            tt.cnt = tmp.cnt + 1; //该问题分锅人数+1
            tt.id = tmp.id;
            tt.y = a[tmp.id] * a[tmp.id] * (1.0 / tt.cnt - 1.0 / (tt.cnt + 1));
            q.push(tt);
        }
        double ans = 0;
        while (!q.empty()) {
            node tt = q.top();
            ans += tt.cnt * (av - a[tt.id] / tt.cnt) * (av - a[tt.id] / tt.cnt);
            q.pop();
        }
        printf("Case #%d: ", cas);
        printf("%.10f\n", ans / m);
    }
    return 0;
}
/*
因为每个问题至少要有一人背锅,所以只要考虑剩下的m-n个人即可。
因为要让方差尽可能小,所以我们需要让每次一个人产生的贡献尽可能大。
所以每次让一个人为他加入前后方差之差最大的那个问题背锅就是最优的。
化简前后方差的差值:
num*(a/num-x)^2-(num+1)*(a/(num+1)-x)^2     (num为分锅人数,a为锅的大小,x为均值)
最后得到的表达式为(a^2)*(1/num-1/(num+1))-x² 由于x²为固定值,是一个常数,
维护队列的时候让(a^2)*(1/num-1/(num+1))最大即可
用优先队列或者set维护a^2/(num*(num+1))即可.
*/

F-HDU-5981
学长说是金牌题
暂时不用研究了
放两篇题解
https://blog.csdn.net/Jaihk662/article/details/77435217
https://blog.csdn.net/lych_cys/article/details/53149585

赛况记录:
A - RE1次(少写条件);
B - WA1次(背错板子);
C - 未完成(矩阵乘法Orz);
D - 未完成 (没看懂题意);
E - 未完成 ;
F - 未完成 (还好没细想233);
contest链接

内容概要:本文档详细介绍了基于直驱永磁同步发电机(PMSG)的1.5MW风力发电系统在Simulink环境下的建模与仿真全过程,涵盖了风力机空气动力学模型、PMSG电磁特性建模、不可控整流与逆变电路、直流环节、空间矢量脉宽调制(SVPWM)技术以及核心控制策略的设计。重点实现了最大功率点跟踪(MPPT)控制以提升风能捕获效率,并构建了电压外环与电流内环协同工作的双闭环控制系统,通过仿真验证了系统在不同风速条件下稳定运行的能力及动态响应性能。; 适合人群:适用于具备电力系统、电机控制理论基础及Simulink仿真操作经验的研究生、科研人员和从事新能源发电系统开发的工程技术人员;特别适合正在进行风电系统建模、控制算法研究或完成相关毕业设计的专业人士。; 使用场景及目标:①深入理解直驱式PMSG风力发电系统的整体架构与工作机理;②掌握从物理部件建模到控制策略实现的完整Simulink仿真流程;③学习并复现MPPT控制、双闭环控制等关键技术方案;④为后续开展低电压穿越、并网稳定性分析、故障诊断等高课题提供可靠的仿真平台支撑。; 阅读建议:建议结合Matlab/Simulink软件动手实践,逐模块搭建模型,重点关注各控制环节的参数设计与调试方法,同时可参照文中提供的其他风电相关资源进行拓展学习与对比分析。
已经博主授权,源码转载自 https://pan.quark.cn/s/868afdd63918 在信息技术领域中,前端开发构成了Web应用程序构建的关键环节,而登录注册页面则是用户与网站进行互动的起始界面。"150款web登录注册页面模板(附带效果图+源码)"这一资源为前端工程师们提供了一系列预先设计的界面组件,支持他们迅速构建既美观又实用的登录及注册界面,从而有效缩减开发周期并增强工作效率。 这些模板囊括了多样化的风格和设计潮流,涵盖了扁平化设计、Material Design、渐变色彩、暗黑模式等,能够适应不同项目的特定要求。在设计中强调用户体验,通过科学的布局安排,提升了表单的便捷操作性和可辨识度,并且不忽视视觉层面的吸引力。设计师通常会关注自适应设计,保证页面在多种设备(涵盖手机、平板及桌面电脑)上均能呈现良好的视觉效果。 这些模板均配备了源代码,使得开发者得以深入探究并个性化定制每个构成部分,涉及HTML的页面构造、CSS的样式修饰以及JavaScript的交互逻辑。HTML主要承担着页面基础结构的搭建,CSS用于实现页面美化与布局控制,JavaScript则常用于处理表单验证和交互效果。对于那些精通这三种技术的开发者而言,他们可以根据个人需求对模板进行功能扩展和样式调整。 在实际部署时,登录注册页面通常需要集成基础的输入项,例如用户名、密码、电子邮箱等,并且必须重视安全性考量,诸如密码强度指引、验证码系统等。除此之外,为了优化用户体验,还可能集成记住密码、自动填充、社交平台登录(例如微信、QQ、微博)等功能。 在开发阶段,前端工程师还需关注Web标准和无障碍访问(WCAG)规范,确保页面的通用友好性,这包括视障、听障或其他有特殊需求的用户群体。具体措施涉及标...
源码直接下载地址: https://pan.quark.cn/s/9af8b9f95652 ### Multisim模型的导入和使用 ### 一、引言 随着电子设计自动化(EDA)工具的进步,Multisim已经成为电子工程师进行电路仿真、分析和设计的关键工具之一。借助Multisim,工程师们能够便捷地构建电路模型,并对电路进行仿真验证。本文将系统阐述如何在Multisim中导入并运用芯片仿真模型,这对于提升电子产品的研发效能具有显著价值。 ### 二、Multisim中构建新元器件 构建新元器件是Multisim中的核心功能,特别是对于那些需要特定模型或无法从Multisim库中直接获取的元器件来说更为关键。以下为构建新元器件的具体流程: ##### 步骤1:录入元器件信息 在Multisim中启动“Component Wizard”,即元器件向导,开始创建新的元器件。首先需要录入元器件的基本资料,包括型号、主要功能、类型等。这些资料将有助于用户更高效地管理和检索元器件。 ##### 步骤2:录入封装信息 接下来需要设定元器件的封装信息。在这一环节中,用户需要依据实际芯片的封装规格来选择适宜的引脚数量。同时,还需明确是构建单一部件元器件还是复合部件元器件。如果是复合部件元器件,则必须确保引脚数量与符号中使用的引脚数量保持一致。 ##### 步骤3:录入符号信息 在此步骤中,用户可以编辑元器件在仿真过程中的显示符号。编辑符号可以通过三种途径进行:直接编辑、从数据库中复制现有符号或复制当前符号以备将来使用。编辑符号时应注重其在电路图中的可辨识度和清晰度。 ##### 步骤4:设定管脚参数 在该步骤中,用户需要参照数据手册上的管脚顺序为每个管脚命名,并选择恰当的类型。...
代码转载自:https://pan.quark.cn/s/7b1a6710052c Vivado 2018.2 与 ModelSim 的协同仿真操作 Vivado 2018.2 是由 Xilinx 公司开发的一款用于 FPGA 设计的工具,它包含了丰富的设计和仿真功能。然而,在实际应用过程中,用户可能会遇到其自带的仿真工具运行效率不高的问题。为了提升仿真效率并简化设计验证流程,可以考虑采用第三方仿真工具 ModelSim。ModelSim 是一款性能卓越且市场应用广泛的仿真软件,接下来的内容将详细阐述如何实现 Vivado 2018.2 与 ModelSim 的联合使用。 配置 ModelSim 的安装路径 在使用 Vivado 2018.2 时,首先需要配置 ModelSim 的安装位置。用户可以通过点击 Vivado 菜单中的“Tools”——>“Settings...”选项,然后在弹出的设置界面中,选择“Tool Settings”下的“3rd Party Simulators”选项卡。在“Install Paths”区域,找到“ModelSim”条目,并在此输入或选择 ModelSim 的具体安装路径。 执行器件库编译操作 在 ModelSim 的安装目录下,创建一个名为 xilinx_lib 的子文件夹。随后,在 Vivado 菜单中通过“Tools”——>“Compile Simulation Libraries...”选项启动器件库编译流程,并设定相应的编译参数。在打开的对话框里,将仿真工具选择为“ModelSim Simulator”,保持语言和库的默认设置不变,同时指定编译器件库的存放位置和 ModelSim 可执行文件的路径。 ...
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值