暑假集训CSP提高模拟6
1.高一上七月上旬日记2.牛客周赛 Round 493.Denso Create Programming Contest 2024(AtCoder Beginner Contest 361)4.NOIP2024模拟15.NOIP2024模拟26.高一上七月中旬日记7.NOIP2024模拟38.CSP提高组模拟19.暑假集训CSP提高模拟110.暑假集训CSP提高模拟211.暑假集训CSP提高模拟312.暑假集训CSP提高模拟413.高一上七月下旬日记14.暑假集训 加赛115.暑假集训CSP提高模拟5
16.暑假集训CSP提高模拟6
17.加赛218.暑假集训CSP提高模拟719.暑假集训CSP提高模拟820.暑假集训CSP提高模拟921.暑假集训CSP提高模拟1022.暑假集训CSP提高模拟1123.暑假集训CSP提高模拟12暑假集训CSP提高模拟6
组题人: @KafuuChinocpp | @Chen_jr
P162. 花间叔祖
-
原题: [ARC148A] mod M
-
不难发现,最终答案只有
和 两种取值。 -
若
,则最终答案为 ;否则,答案为 。 -
又因为
当且仅当 。进而得到 ,取 即可。点击查看代码
int a[200010]; int gcd(int a,int b) { return b?gcd(b,a%b):a; } int main() { int n,d=0,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } sort(a+1,a+1+n); for(i=2;i<=n;i++) { d=gcd(d,a[i]-a[i-1]); } cout<<((d==1)?2:1)<<endl; return 0; }
-
赛时写得比较唐,取
的最小非 公因数,质因数分解后开桶记录质因子出现次数。因为 内质因子数量不超过 所以时空复杂度可以接受。点击查看代码
int a[200010],prime[200010],c[200010],len=0; void divede(int x) { for(int i=2;i*i<=x;i++) { if(x%i==0) { len++; prime[len]=i; c[len]++; while(x%i==0) { x/=i; } } } if(x>1) { len++; prime[len]=x; c[len]++; } } int main() { int n,flag=0,x,pos=0,i,j; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } for(i=2;i<=n;i++) { if(a[i]!=a[i-1]) { pos=i; break; } } if(pos!=0) { divede(abs(a[pos]-a[pos-1])); for(i=2;i<=n;i++) { if(i!=pos) { x=abs(a[i]-a[i-1]); for(j=1;j<=len;j++) { c[j]+=(x%prime[j]==0); } } } for(i=1;i<=len;i++) { flag|=(c[i]==n-1); } } else { flag=1; } cout<<((flag==0)?2:1)<<endl; return 0; }
P150. 合并r
-
部分分
:当 时,输出1
。
-
设
表示填到第 个数时元素和为 的方案数,此时可以选择填 或让先前填的数都除以 ,故状态转移方程为 ,边界为 。点击查看代码
const ll p=998244353; ll f[5010][5010]; int main() { ll n,k,i,j; cin>>n>>k; f[0][0]=1; for(i=1;i<=n;i++) { for(j=i;j>=1;j--) { f[i][j]=f[i-1][j-1]; if(2*j<=i) { f[i][j]=(f[i][j]+f[i][2*j])%p; } } } cout<<f[n][k]<<endl; return 0; }
P139. 回收波特
-
部分分
-
: 暴力枚举即可。点击查看代码
ll x[300010],ans[300010]; int main() { ll n,m,d,i,j; scanf("%lld%lld",&n,&m); for(i=1;i<=n;i++) { scanf("%lld",&x[i]); } for(i=1;i<=m;i++) { scanf("%lld",&d); for(j=1;j<=n;j++) { if(ans[j]==0) { x[j]+=((x[j]>0)?-d:d); if(x[j]==0) { ans[j]=i; } } } } for(i=1;i<=n;i++) { if(ans[i]!=0) { printf("Yes %lld\n",ans[i]); } else { printf("No %lld\n",x[i]); } } return 0; }
-
-
正解
- 充分发扬人类智慧,我们发现任一时刻,若两个点关于原点对称则它们此后的位置一定一直关于原点对称。
- 波特是动的,但原点是不动的。考虑反过来,让原点动,波特不动。
- 考虑维护值域,预处理出所有点的答案,最后进行询问。
- 每次原点移动后将区间分成在原点左侧、在原点上、在原点右侧三个部分,类似启发式合并,将小区间对称到大区间里,建边方便继承答案,然后将小区间删掉。由于每个点至多被删除
次所以处理操作时间复杂度为 。 - 最后再
一遍处理出没删掉的点的答案。
点击查看代码
struct node { int nxt,to; }e[2000010]; int head[2000010],x[2000010],dfn[2000010],pos[2000010],vis[2000010],cnt=0; void add(int u,int v) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt; } void dfs(int x) { vis[x]=1; for(int i=head[x];i!=0;i=e[i].nxt) { if(vis[e[i].to]==0) { if(dfn[x]==0) { pos[e[i].to]=-pos[x];//不能停,坐标取反 } else { dfn[e[i].to]=dfn[x];//能停,直接继承 } dfs(e[i].to); } } } int main() { int n,m,l=1,r=1000000,d,mid=0,dir=0,i,j; cin>>n>>m; for(i=1;i<=n;i++) { cin>>x[i]; } for(i=1;i<=m;i++) { cin>>d; mid+=(dir==0)?d:-d; if(l<=mid&&mid<=r) { dfn[mid]=i; if(mid-1-l+1<=r-(mid+1)+1) { for(j=l;j<=mid-1;j++) { add(mid*2-j,j); } l=mid+1; dir=0; } else { for(j=mid+1;j<=r;j++) { add(mid*2-j,j); } r=mid-1; dir=1; } } else { dir=(mid>r); } } for(i=l;i<=r;i++) { if(dfn[i]==0) { pos[i]=i-mid; } dfs(i); } for(i=1;i<=l-1;i++) { if(dfn[i]!=0) { dfs(i); } } for(i=r+1;i<=1000000;i++) { if(dfn[i]!=0) { dfs(i); } } for(i=1;i<=n;i++) { if(dfn[x[i]]==0) { cout<<"No "<<pos[x[i]]<<endl; } else { cout<<"Yes "<<dfn[x[i]]<<endl; } } return 0; }
T3342. 斗篷
-
发现数据的输入格式是有一定限制的。
-
只考虑统计形如△的三角形,然后将整个图翻转过来求解。
-
预处理出
分别表示 向左上/右上/左边所能延伸的最长距离。 -
枚举
作为三角形的右下角,则能进行转移的三角形长度 若满足 则对答案产生 的贡献。- 自觉忽略
---
的影响。
- 自觉忽略
-
观察到
,即 会对 产生 的贡献,进行差分,扫描线维护一下即可。具体地,在 的位置进行加一,在 进行减一,vector
存一下要减哪些数的位置。点击查看代码
struct BIT { ll c[12010]; void init() { memset(c,0,sizeof(c)); } ll lowbit(ll x) { return (x&(-x)); } void update(ll n,ll x,ll val) { for(ll i=x;i<=n;i+=lowbit(i)) { c[i]+=val; } } ll getsum(ll x) { ll ans=0; for(ll i=x;i>=1;i-=lowbit(i)) { ans+=c[i]; } return ans; } }T; short ld[6010][12010],rd[6010][12010],l[6010][12010]; char s1[6010][12010],s2[6010][12010]; vector<ll>d[12010]; string t; ll ask(char s[6010][12010],ll n,ll m) { memset(ld,0,sizeof(ld)); memset(rd,0,sizeof(rd)); memset(l,0,sizeof(l)); ll ans=0,i,j,k; for(i=1;i<=n;i+=2) { T.init(); for(j=(s[i][1]==' '?3:1),k=1;j<=m;j+=4,k++) { ld[i][j]=(s[i-1][j-1]!=' '&&i-2>=0&&j-2>=0)?ld[i-2][j-2]+1:0; rd[i][j]=(s[i-1][j+1]!=' '&&i-2>=0&&j+2<=m)?rd[i-2][j+2]+1:0; l[i][j]=(s[i][j-1]!=' '&&j-4>=0)?l[i][j-4]+1:0; ans+=T.getsum(k)-T.getsum(k-min(ld[i][j],l[i][j])-1); T.update(m,k,1); d[k+rd[i][j]].push_back(k); while(d[k].empty()==0) { T.update(m,d[k].back(),-1); d[k].pop_back(); } } } return ans; } int main() { ll r,c,n,m,i,j; cin>>r>>c; n=2*r-1; m=2*c-1; for(i=0;i<=n;i++) { getline(cin,t); while(t.size()<m) { t+=' '; } s1[i][0]=' '; for(j=0;j<=m-1;j++) { s1[i][j+1]=t[j]; } } for(i=1;i<=n;i++) { s2[i][0]=' '; for(j=1;j<=m;j++) { s2[i][j]=s1[n-i+1][m-j+1]; } } cout<<ask(s1,n,m)+ask(s2,n,m)<<endl; return 0; }
总结
没想到直接取 ,导致要质因数分解。
后记
-
题解名称为
hustDelov.md
。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18319969,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 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】