首页 > 其他分享 >[73] (NOIP集训) NOIP2024 加赛 7

[73] (NOIP集训) NOIP2024 加赛 7

时间:2024-11-22 18:07:58浏览次数:1  
标签:int sum times 73 加赛 ffffff id NOIP2024 2k

DZ:你逆元过了?
DZ:我去,那造数据的比较牛
DZ:出题人精心构造的坑,造数据的一下就给弄没了

这场真像 NOIP 难度吗,感觉还不如 CSP

flowchart TB A(镜的绮想) style A color:#ffffff,fill:#00c0c0,stroke:#ffffff

两个点能对称当且仅当横坐标相等

\(nm\) 枚举所有点,横坐标相等的记录其对称轴位置,暴力给对称轴位置贡献加一

最后统计哪个位置贡献多即可

#include<bits/stdc++.h>
using namespace std;
int n,m;
struct node{
    int x,y;
};
node s[5001],x[5001];
#include<bits/extc++.h>
using namespace __gnu_pbds;
gp_hash_table<int,int>mp;
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        cin>>s[i].x>>s[i].y;
    }
    for(int i=1;i<=m;++i){
        cin>>x[i].x>>x[i].y;
    }
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            if(s[i].x==x[j].x){
                mp[s[i].y+x[j].y]++;
            }
        }
    }
    int ans=0;
    for(auto i:mp){
        ans=max(ans,i.second);
    }
    cout<<ans<<'\n';
}
flowchart TB A(万物有灵) style A color:#ffffff,fill:#00c0c0,stroke:#ffffff

最大独立集定义:\(\max(|S|)\rightarrow \forall x\in S,y\in S,(x,y)\not\in E\),还好学二分图的时候没摆烂

结论:从叶节点开始隔一层选一层最优,不用证,因为这是树,下一层的节点数量严格不低于上一层,所以这样选最优

先考虑 \(k\) 为偶数的情况

考虑每一层对答案的贡献就是该层的节点数目,而(以 \(k=4\) 为例)

\(n\) 节点数
\(0\) \(1\)
\(1\) \(k_0\)
\(2\) \(k_0k_1\)
\(3\) \(k_0k_1k_2\)
\(4\) \(k_0k_1k_2k_3\)
\(5\) \(k_0^2k_1k_2k_3\)
\(6\) \(k_0^2k_1^2k_2k_3\)

可以发现一个以 \(k\) 为周期的规律:每一个周期都是上一个周期乘以 \(k_0k_1k_2k_3\)

设第一个周期的答案为 \(s\)(由于 \(k\) 较小,这是可以直接求的),那么答案就是:

\[s\times(1+\prod k_i+(\prod k_i)^2+\cdots) \]

项数就是 \(\lfloor\frac{n+1}{k}\rfloor\),后面可能会有剩下的一小点,还是暴力处理即可

现在的问题就变成求这一大坨等比数列,毒瘤出题人把逆元卡了(然而并没有),因此可以考虑矩阵快速幂或者倍增等方法

矩阵快速幂的写法极其简单,不难构造出初始矩阵 \(\left[\begin{matrix}0&1\end{matrix}\right]\) 和转移矩阵 \(\left[\begin{matrix}1&0\\1&\prod k_i\end{matrix}\right]\),直接快速幂取第一位即可

这是 \(k\) 为偶数的情况,那么 \(k\) 为奇数的情况咋处理,这个就比较简单了,直接 \(k\) 乘二就行了

#include<bits/stdc++.h>
#include<matrix.h>
using namespace std;
#define int long long
int n,k,p;
int a[500001];
matrix<int,4>mat,mat2;
int db(int x,int t){  //cal for 1+x+x^2+x^3+...+x^(t-1)
	mat.packed_clear({
		{1,0},
		{1,x}
	});
	mat2.packed_clear({
		{0,1}
	});
	mat.setmod(p);
	mat2.setmod(p);
	return (mat2*(mat|t))[1][1];
}
signed main(){
    cin>>n>>k>>p;
    for(int i=0;i<=k-1;++i){
        cin>>a[i];
    }
    int s=0,sizee=1;
    for(int i=0;i<=2*k-1;++i){
        if((i&1)==(n&1)) s=(s+sizee)%p;
        sizee=sizee*a[i%k]%p;
    }
    int tm=(n+1)/(2*k);
    int ans=(s*db(sizee,tm)%p)%p;
    sizee=power(sizee,tm);
    for(int i=tm*2*k;i<=n;++i){
        if((i&1)==(n&1)) ans=(ans+sizee)%p;
        sizee=sizee*a[i%k]%p;
    }
    cout<<ans<<endl;
}
flowchart TB A(白石溪) style A color:#ffffff,fill:#00c0c0,stroke:#ffffff

\(n^2\) DP 比较简单

$n^2$
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,c,d;
int a[1000001],b[1000001];
int f[3001][3001]; //放了 i 个,其中有 j 个是红色的
signed main(){
    cin>>n>>c>>d;
    for(int i=1;i<=n;++i){
        cin>>a[i]>>b[i];
    }
    for(int i=1;i<=n;++i){
        for(int j=0;j<=i;++j){
            if(j!=i) f[i][j]=max(f[i][j],f[i-1][j]+b[i]+c*j);   //放蓝色
            if(j!=0) f[i][j]=max(f[i][j],f[i-1][j-1]+a[i]+d*(i-j)); //放红色
        }
    }
    int ans=0;
    for(int i=0;i<=n;++i){
        ans=max(ans,f[n][i]);
    }
    cout<<ans<<'\n';
}

考虑贪心,所有红色点的贡献是 \(\sum a_i+d\times\sum\limits^{i-pre}_{j=1}j\),其中 \(pre\) 是 \([1,i]\) 中红色点的个数,蓝色点同理

考虑拆出 \(\sum a_i+d\times\sum\limits i\),可以发现,拆出来的这部分对每个点是独立的,剩下的那部分构成了一个等差数列,其值只与项数(红色点的个数)有关,因此直接枚举红色点的个数,这样后半段贡献就已知了,只需要最大化前半段贡献

先假设全是蓝色点,将一个蓝色点 \(i\) 变成一个红色点,对前半部分答案的贡献是 \((a_i+d\times i)-(b_i+c\times i)=a_i-b_i+i\times(d-c)\),可以直接按这个值排序,然后贪心选点即可

还有一种奇怪的写法是直接钦定所有的贡献都是红色点产生的(和前面的蓝色点产生 \(c\) 的贡献,和后面的蓝色点产生 \(d\) 的贡献),这样也能做,写起来怪怪的

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,c,d;
int a[1000001],b[1000001];
int id[1000001];
inline int val(int x){
    return a[x]-b[x]+(x-1)*d+(n-x)*c;
}
signed main(){
    cin>>n>>c>>d;
    int sum=0,ans=0;
    for(int i=1;i<=n;++i){
        cin>>a[i]>>b[i];
        id[i]=i;
        sum+=b[i];
    }
    ans=sum;
    iota(id+1,id+n+1,1);
    sort(id+1,id+n+1,[](int x,int y){return val(x)>val(y);});
    for(int i=1;i<=n;++i){
        sum+=val(id[i]);
        ans=max(ans,sum-i*(i-1)/2*d-i*(i-1)/2*c);
    }
    cout<<ans<<endl;
}

这是什么

标签:int,sum,times,73,加赛,ffffff,id,NOIP2024,2k
From: https://www.cnblogs.com/HaneDaCafe/p/18563286

相关文章

  • 22207334-章莲祥-第二次博客
    一、前言这两次大作业中关于电路的分析与设计的开发让我对java这门语言的理解和应用又得到了提升,面向对象的编程对于解决实际生活中的问题拥有其他编程方式所没有的优势。在两次的类设计中我的考虑并不周全,忽视了电路设备之间共性从而没怎么用到继承,这个问题在第一次串联电路的......
  • springboot西餐主题网站-计算机毕业设计源码73020
    目录摘要1绪论1.1选题背景与意义1.2国内外研究现状1.3论文结构与章节安排2系统分析2.1可行性分析2.2系统流程分析2.2.1数据流程2.2.2业务流程2.3 系统功能分析2.3.1功能性分析2.3.2非功能性分析2.4 系统用例分析2.5本章小结3 系统总......
  • 『模拟赛』多校A层冲刺NOIP2024模拟赛25
    Rank极限了,感觉还行感觉T3不是一般人可做的,遂先来写赛记。A.图签。本来不是很一眼的,但看到给了这个和这个然后就很一眼了。用longlong状压每个点所有操作下是否属于S/T集合的状态,那么发现对于一条边\((i,j)\),只有某一次操作满足\(i\inS\)且\(j\inT\)......
  • P5738 【深基7.例4】歌唱比赛
    先说思路:根据题目易知,要对m个评委的评分进行排序,那么就要用到排序函数,这里我用快速排序,当然也可以用其他排序方式,怎样简单怎样来,之后在对排序好的元素,去掉最高值和最低值,算出平均数,再将平均数输到一个新的数组中,输出最大值。(记得输出的是double类型)以下是代码实现:#include......
  • NOIP2024 前集训:NOIP2024加赛 6
    前言music《身骑白马》我爱谁跨不过从来也不觉得错自以为抓着痛就能往回忆里躲偏执相信着受诅咒的水晶球阻挡可能心动的理由而你却靠近了逼我们视线交错原地不动或向前走突然在意这分钟眼前荒沙弥漫了等候耳边传来孱弱的呼救追赶要我爱的不保留......
  • [68] (NOIP集训) NOIP2024 加赛 5
    恐将成为我改题时间最长的一场(也是分最低的一场)码长断崖式领先了flowchartTB A(暴力操作) styleAcolor:#ffffff,fill:#00c0c0,stroke:#ffffff首先你肯定要让小于(等于)中位数的数变小,将较大的值变小是毫无意义的,因为即使你完全不管他们,也不会对答案造成任何影响,白白浪费费......
  • [赛记] NOIP2024加赛5
    暴力操作(opt)30pts这个错解可反悔贪心30pts;考虑正解,我们只需考虑前$\fracn2+1$小的数即可;考虑二分出一个中位数$mid$,那么我们要让大于它的都用最小的代价变小;考虑如何求这个最小的代价,因为$\lfloor\frac{\lfloor\fracab\rfloor}{c}\rfloor=\lfloor\frac{ab......
  • [赛记] 多校A层冲刺NOIP2024模拟赛24
    选取字符串60pts直接暴力60pts;这题难点在于读懂题把。。。考虑建出$KMP$树,然后在其中选出$k$个数,他们的$LCA$的深度的平方和就是这个答案,然后简单统计一下即可;具体地,把$KMP$树建出来,然后求每$k$个点的$LCA$的深度的平方和即可,最后乘上方案数(总的减去......
  • 多校A层冲刺NOIP2024模拟赛24
    选取字符串建出失配树以后直接dp就好了。但场上现推的kmp……点此查看代码#include<bits/stdc++.h>usingnamespacestd;#definerep(i,s,t,p)for(inti=s;i<=t;i+=p)#definedrep(i,s,t,p)for(inti=s;i>=t;i-=p)#ifdefLOCALFILE*InFile=freope......
  • NOIP2024加赛6
    一签三计数,罚坐了。草莓简单贪心,随便贪就过了。点此查看代码#include<bits/stdc++.h>usingnamespacestd;#definerep(i,s,t,p)for(inti=s;i<=t;i+=p)#definedrep(i,s,t,p)for(inti=s;i>=t;i-=p)#ifdefLOCAL FILE*InFile=freopen("in.in","r......