NOIP2024加赛7
1.高一上十一月上旬日记2.NOIP2024加赛13.多校A层冲刺NOIP2024模拟赛184.NOIP2024加赛25.多校A层冲刺NOIP2024模拟赛196.多校A层冲刺NOIP2024模拟赛207.NOIP2024(欢乐)加赛38.高一上十一月中旬日记9.NOIP2024加赛410.多校A层冲刺NOIP2024模拟赛2111.2025--炼石计划-- 11 月 13 日 --NOIP 模拟赛 #2012.NOIP2024加赛513.NOIP2024加赛614.多校A层冲刺NOIP2024模拟赛2415.高一上十一月下旬日记16.多校A层冲刺NOIP2024模拟赛25
17.NOIP2024加赛7
18.2025--炼石计划-- 11 月 23 日 --NOIP 模拟赛 #2319.【MX-S7】梦熊 NOIP 2024 模拟赛 3 & SMOI Round 2(同步赛)20.多校A层冲刺NOIP2024模拟赛2621.NOIP2024加赛822.多校A层冲刺NOIP2024模拟赛27终结篇NOIP2024加赛7
题面来源: 2023NOIP A层联测15
HZTG5683. 镜的绮想 (mirror)
-
从点对本身考虑,开个桶统计即可。
点击查看代码
int x[5010],y[5010],xx[5010],yy[5010],f[4000010]; int main() { #define Isaac #ifdef Isaac freopen("mirror.in","r",stdin); freopen("mirror.out","w",stdout); #endif int n,m,ans=0,i,j; cin>>n>>m; for(i=1;i<=n;i++) { cin>>x[i]>>y[i]; } for(i=1;i<=m;i++) { cin>>xx[i]>>yy[i]; } for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(x[i]==xx[j]) { f[y[i]+yy[j]+2000000]++; } } } for(i=0;i<=4000000;i++) { ans=max(ans,f[i]); } cout<<ans<<endl; return 0; }
HZTG5684. 万物有灵 (animism)
-
手摸最大独立集的式子后发现选与不选之间的大小关系隔一层就交换一次。
-
部分分
: 计算。
点击查看代码
ll a[500010],f[2][2]; ll qadd(ll a,ll b,ll p) { return a+b>=p?a+b-p:a+b; } int main() { #define Isaac #ifdef Isaac freopen("animism.in","r",stdin); freopen("animism.out","w",stdout); #endif ll n,k,p,i,j; scanf("%lld%lld%lld",&n,&k,&p); for(i=0;i<=k-1;i++) { scanf("%lld",&a[i]); } for(i=n,j=0;i>=0;i--,j^=1) { f[i&1][0]=a[i%k]*f[(i+1)&1][j]%p; f[i&1][1]=qadd(a[i%k]*f[(i+1)&1][0]%p,1,p); } printf("%lld\n",f[0][j]); return 0; }
-
正解
- 考虑暴力处理出
层的贡献,剩下的周期 统一计算。 - 将式子暴力展开后发现是个等比数列求和的形式,因为不保证模数为质数,故倍增/矩阵快速幂加速维护即可。
- 倍增写法跟快速幂差不多。
- 矩阵快速幂形如
。
- 因为
为奇数时需要特判,不妨直接钦定 为偶数,将周期直接翻倍。
点击查看代码
ll a[1000010],mul[1000010]; ll qpow(ll a,ll b,ll p) { ll ans=1; while(b) { if(b&1) { ans=ans*a%p; } b>>=1; a=a*a%p; } return ans; } ll qsum(ll q,ll n,ll p) { if(n<=1) { return (n==1); } ll tmp=qsum(q,n/2,p),sum=(tmp*qpow(q,n/2,p)%p+tmp)%p; return (n%2==0)?sum:(sum*q%p+1)%p; } int main() { #define Isaac #ifdef Isaac freopen("animism.in","r",stdin); freopen("animism.out","w",stdout); #endif ll n,k,p,sum,ans=0,tmp,i; scanf("%lld%lld%lld",&n,&k,&p); for(i=0;i<k;i++) { scanf("%lld",&a[i]); a[i+k]=a[i]; } k*=2; mul[0]=a[0]; for(i=1;i<k;i++) { mul[i]=mul[i-1]*a[i]%p; } for(i=(n+1)%2;i<k;i+=2) { ans=(ans+mul[i])%p; } ans=(ans*qsum(mul[k-1],n/k,p)%p+(n+1)%2)%p; tmp=qpow(mul[k-1],n/k,p); for(i=(n+1)%2;i<n%k;i+=2) { ans=(ans+mul[i]*tmp)%p; } printf("%lld\n",ans); return 0; }
- 考虑暴力处理出
HZTG5685. 白石溪 (creek)
-
部分分
- 测试点
: 的 。 - 测试点
:搭配产生的美丽度无意义,直接取 。
点击查看代码
ll f[2][1000010],a[1000010],b[1000010]; int main() { #define Isaac #ifdef Isaac freopen("creek.in","r",stdin); freopen("creek.out","w",stdout); #endif ll n,c,d,ans=0,i,j; scanf("%lld%lld%lld",&n,&c,&d); for(i=1;i<=n;i++) { scanf("%lld%lld",&a[i],&b[i]); } if(c==0&&d==0) { for(i=1;i<=n;i++) { ans+=max(a[i],b[i]); } } else { memset(f,-0x3f,sizeof(f)); f[0][0]=0; for(i=1;i<=n;i++) { for(j=0;j<=i;j++) { f[i&1][j]=f[(i-1)&1][j]+b[i]+j*c; if(j-1>=0) { f[i&1][j]=max(f[i&1][j],f[(i-1)&1][j-1]+a[i]+((i-1)-(j-1))*d); } } } for(i=0;i<=n;i++) { ans=max(ans,f[n&1][i]); } } printf("%lld\n",ans); return 0; }
- 测试点
-
正解
已经难以优化,考虑贪心。- 设
表示 中与 颜色相同的石子个数。若第 个石子为红色,则其贡献为 ,蓝色的贡献为 。 - 以红色为例,将贡献拆成
和 两部分。从全局来看,后者只与红色石子总数有关。 - 不妨先钦定全为蓝色石子,然后考虑枚举红色石子的总数只统计前者的贡献。用红色更换蓝色的影响为
,排序后贪心选择即可。
点击查看代码
ll a[1000010],b[1000010],e[1000010]; int main() { #define Isaac #ifdef Isaac freopen("creek.in","r",stdin); freopen("creek.out","w",stdout); #endif ll n,c,d,ans=0,sum=0,i; scanf("%lld%lld%lld",&n,&c,&d); for(i=1;i<=n;i++) { scanf("%lld%lld",&a[i],&b[i]); e[i]=a[i]-b[i]+i*(d-c); sum+=b[i]+i*c; } sort(e+1,e+1+n,greater<ll>()); for(i=0;i<=n;i++) { sum+=e[i]; ans=max(ans,sum-i*(i+1)/2*d-(n-i)*(n-i+1)/2*c); } printf("%lld\n",ans); return 0; }
HZTG5686. 上山岗 (uphill)
-
部分分
:枚举全排列。
点击查看代码
int c[500010],w[500010]; vector<int>ans,tmp; bool cmp() { for(int i=0;i<ans.size();i++) { if(ans[i]<tmp[i]) { return true; } if(ans[i]>tmp[i]) { return false; } } return false; } int main() { #define Isaac #ifdef Isaac freopen("uphill.in","r",stdin); freopen("uphill.out","w",stdout); #endif int n,sum=-1,num,i; cin>>n; for(i=1;i<=n;i++) { cin>>c[i]; } for(i=1;i<=n;i++) { cin>>w[i]; tmp.push_back(w[i]); } sort(tmp.begin(),tmp.end()); do { num=0; for(i=1;i<=n;i++) { num+=(tmp[i-1]>c[i]); } if(num>sum) { sum=num; ans=tmp; } else { if(num==sum&&cmp()==true) { ans=tmp; } } }while(next_permutation(tmp.begin(),tmp.end())); for(i=0;i<ans.size();i++) { cout<<ans[i]<<" "; } return 0; }
-
正解
- 把
放在一起升序排序后将 视为 , 视为 ,那么最多登顶次数就是前缀和的最小值 。考虑无用的 来源即可。 - 对于每个选手一定是尽可能往放后面放,顺序线段树上二分找到对应位置分配。依此保证先取到最多登顶次数。
- 接着倒序考虑没有分配到山的选手,优先选择靠前且没有重新分配到选手的山给它;否则进行重新分配并优先选择靠前的山。这个过程中登顶次数不会变少。
点击查看代码
int c[500010],w[500010],ans[500010],pos[500010],id[500010]; struct SMT { struct SegmentTree { int minn; }tree[2000010]; int lson(int x) { return x*2; } int rson(int x) { return x*2+1; } void pushup(int rt) { tree[rt].minn=min(tree[lson(rt)].minn,tree[rson(rt)].minn); } void build(int rt,int l,int r,int c[]) { if(l==r) { tree[rt].minn=c[l]; return; } int mid=(l+r)/2; build(lson(rt),l,mid,c); build(rson(rt),mid+1,r,c); pushup(rt); } void update(int rt,int l,int r,int pos,int val) { if(l==r) { tree[rt].minn=val; return; } int mid=(l+r)/2; if(pos<=mid) { update(lson(rt),l,mid,pos,val); } else { update(rson(rt),mid+1,r,pos,val); } pushup(rt); } int query1(int rt,int l,int r,int k) { if(l==r) { return tree[rt].minn<k?l:-1; } int mid=(l+r)/2; if(tree[lson(rt)].minn<k) { return query1(lson(rt),l,mid,k); } else { return query1(rson(rt),mid+1,r,k); } } int query2(int rt,int l,int r,int k) { if(l==r) { return tree[rt].minn<k?l:-1; } int mid=(l+r)/2; if(tree[rson(rt)].minn<k) { return query2(rson(rt),mid+1,r,k); } else { return query2(lson(rt),l,mid,k); } } }sec,fir; int main() { #define Isaac #ifdef Isaac freopen("uphill.in","r",stdin); freopen("uphill.out","w",stdout); #endif int n,tmp,i; cin>>n; for(i=1;i<=n;i++) { cin>>c[i]; } for(i=1;i<=n;i++) { cin>>w[i]; } sort(w+1,w+1+n); fir.build(1,1,n,c); sec.build(1,1,n,ans); for(i=1;i<=n;i++) { tmp=fir.query2(1,1,n,w[i]); if(tmp!=-1) { pos[i]=tmp; id[tmp]=i; fir.update(1,1,n,tmp,0x7f7f7f7f); } } for(i=n;i>=1;i--) { if(pos[i]==0) { tmp=sec.query1(1,1,n,1); pos[id[tmp]]=0; } else { fir.update(1,1,n,pos[i],c[pos[i]]); tmp=fir.query1(1,1,n,w[i]); } ans[tmp]=w[i]; fir.update(1,1,n,tmp,0x7f7f7f7f); sec.update(1,1,n,tmp,1); } for(i=1;i<=n;i++) { printf("%d ",ans[i]); } return 0; }
- 把
总结
原用来下标移位的桶使用map
代替了,没有在本地测试极限数据,挂了 。 以为矩阵有交换律,遂直接把同一个矩阵的指数合并了,口胡了一个 维护 和 的指数做法,调到最后也没意识到自己做法有问题。 初始化有问题,挂了 。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18563451,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】