AtCoder Beginner Contest 293

题解报告

基本的一些理解和问题都在注释中
A:Swap Odd and Even

//水题 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> using namespace std; int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); string s;cin>>s; int len=s.size(); for(int i=0;i*2<len;i++) swap(s[2*i],s[2*i+1]); cout<<s<<endl; return 0; }

B:Call the ID Number

//水题 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> using namespace std; const int maxn=2e5+10; int num[maxn]; int flag[maxn]; int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int N;cin>>N; for(int i=1;i<=N;i++)cin>>num[i]; for(int i=1;i<=N;i++) if(!flag[i])flag[num[i]]=1; int res=0; for(int i=1;i<=N;i++)if(!flag[i])res++; cout<<res<<endl; for(int i=1;i<=N;i++)if(!flag[i])cout<<i<<' '; cout<<endl; return 0; }

C:Make Takahashi Happy

//水题 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <unordered_map> using namespace std; const int maxn=15; int W[maxn][maxn]; int dirx[2]={0,1}; int diry[2]={1,0}; unordered_map<int,int> mp; int N,M,res; void dfs(int x,int y) { if(x==N&&y==M) { ++res; } else{ for(int i=0;i<2;i++) { int fx=dirx[i]+x; int fy=diry[i]+y; if(fx<=N&&fy<=M&&!mp[W[fx][fy]]) { mp[W[fx][fy]]=1; dfs(fx,fy); mp[W[fx][fy]]=0; } } } return; } int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>N>>M; for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) cin>>W[i][j]; mp[W[1][1]]=1; dfs(1,1); cout<<res<<endl; return 0; }

D:Tying Rope
题目大意: 把一些线连接起来,找联通和环。
我使用的是建图然后暴力搜索,好像并查集也可以做

#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> using namespace std; const int maxn=2e5+10; int vis[maxn]; int vis2[maxn];//这个是里面看的。 struct edge { int R,B; }Edge[maxn]; bool dfs(int u,int dir)//第二个记录哪边不能走 { if(u==0)return false; vis[u]=1; vis2[u]=1; bool res=false; if(dir!=1)//蓝色的不能走 { int Dir=0; if(Edge[Edge[u].R].B==u) Dir=0; else Dir=1; if(vis2[Edge[u].R])return true; else{ res|=dfs(Edge[u].R,Dir); } } if(dir!=0)//红色的不能走 { int Dir=0; if(Edge[Edge[u].B].B==u)Dir=0; else Dir=1; if(vis2[Edge[u].B])return true; else{ res|=dfs(Edge[u].B,Dir); } } return res; } int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int N,M;cin>>N>>M; for(int i=0;i<M;i++) { char op1,op2; int u,v; cin>>u>>op1>>v>>op2; if(op1=='R'){ if(op2=='R'){ Edge[u].R=v; Edge[v].R=u; }else{ Edge[u].R=v; Edge[v].B=u; } }else{ if(op2=='R'){ Edge[u].B=v; Edge[v].R=u; }else{ Edge[u].B=v; Edge[v].B=u; } } } int res1=0,res2=0; for(int i=1;i<=N;i++) { if(!vis[i]) { if(dfs(i,-1))res1++;//1代表红。 else res2++; } } cout<<res1<<' '<<res2<<endl; return 0; }

E:Geometric Progression
题目大意: 求一个等比数列的和后取模。
等比数列有如下性质:
Sn=qSn1+1
可以知道等比数列的前N项的和是可以通过递推式写出来的。可以考虑利用矩阵的乘法实现一步一步的递推
有如下形式:

(Sn+11)=(q101)(Sn1).

S0=0,则有

(Sn1)=(q101)n(01)

从上面可以看出,利用矩阵的快速幂求取n次方后,获得的矩阵的右上角就是Sn
如果这里使用等比数列的求和公式的话会有如下式子:
i=0n1qi=qn1q1,其中q1是要用逆元来取模的,但是这道题目的模数不一定是质数,所以不一定能拿来用,所以不能用这种方法,要用矩阵快速幂。

//等比数列求和 //注意质数,这里的求乘法逆元的时候只有质数才能用来取模,不是质数就不可以。 //这道题的模数是不确定的,所以不能使用逆元。 //然后用矩阵运算的规则 //以后遇到等比数列求和且模不确定的数,就直接用矩阵快速幂。 //矩阵的快速幂适用于有递推公式的。 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #define ll long long using namespace std; void mul(ll A[2][2],ll B[2][2],int MOD) { ll temp[2][2]; memset(temp,0,sizeof(temp)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) temp[i][j]=(temp[i][j]+A[i][k]*B[k][j])%MOD; for(int i=0;i<2;i++) for(int j=0;j<2;j++) A[i][j]=temp[i][j]; } int M_fpow(ll A,ll B,int MOD) { ll res[2][2]{{1,0},{0,1}}; ll M[2][2]={{A,1},{0,1}}; while(B) { if(B&1)mul(res,M,MOD); B>>=1; mul(M,M,MOD); } return res[0][1]; } //X次方取右上角 int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); ll A,B,C;cin>>A>>B>>C; cout<<M_fpow(A,B,C)<<endl; }

F:Zero or One
(我刚开始没读懂题目,还是看了别人的题解才懂的,菜是原罪)
这道题目居然能用二分写,终究是我写的题目少了,想都想不到。

//二分的题目,用所有可能的状态和原来的状态进行匹配 //如果是看进制的话,就可以把一个数分成好几部分来进行判断,但是又不能分很多份 //所以要先处理好一些要分成很多区间的进制,最后剩下的就是比较大的进制,然后对所有的状态进行枚举判断就行了,看看后面的状态是否能有对应的进制来满足。 //这道题主要是根据不同的区间利用不同的算法进行判断。 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #define ll long long using namespace std; bool Invalid(int bit,ll num)//先把一些小的进制枚举掉,那么就可以缩小最后需要枚举的状态的范围 { while(num) { if(num%bit>1)return false; num/=bit; } return true; } int check(ll bit,int state,ll num)//这里是最容易出错的地方,如果没有限制好就非常容易超出去 { __int128 now=0,Now_bit=1;//防止两个乘起来后很大//用__int128 for(int i=0;i<7;i++) { if(state>>i&1) { if(Now_bit>num)return 1;//这里是联合下面一起来限制的,太大了就不行。 now+=Now_bit; } if(now>num)return 1; if(Now_bit<2e18)Now_bit*=bit;//这个累乘法的是很大的比如说bit为1e18那么在只有最后一位是1的时候就有(1e18)^6非常大,要限制 } if(now==num)return 0; else return -1; } bool Has_bit(int state,ll num)//利用状态去找进制,看看能不能找到 { ll l=1001,r=2e18; //二分去找,有判断的条件,有大有小 while(l<r) { ll mid=(l+r)>>1; if(check(mid,state,num)!=-1)r=mid; else l=mid+1; } //最后还要判断下合不合法 return check(l,state,num)==0; } int main(void) { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int T;cin>>T; while(T--) { ll N;cin>>N; ll ans=0; for(int i=2;i<=1000;i++)if(Invalid(i,N))ans++;//先处理前一千以内的进制。 for(int i=1;i<1<<7;i++)if(Has_bit(i,N))ans++; cout<<ans<<endl; } return 0; }

最后一题好像是板子题,但是我不会,哎~~(原因还是懒得学)
学了莫队再说吧。


__EOF__

本文作者WUTONGHUA02
本文链接https://www.cnblogs.com/WUTONGHUA02/p/17216497.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   WUTONGHUA02  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)
点击右上角即可分享
微信分享提示