“九韶杯”河科院程序设计协会第一届程序设计竞赛题目分析以及总结

博客 动态
0 247
优雅殿下
优雅殿下 2022-03-13 18:56:30
悬赏:0 积分 收藏

“九韶杯”河科院程序设计协会第一届程序设计竞赛题目分析以及总结

还是有很多不足的,模拟思维还需加强,还有一直被诟病的图论

一:6的个数;

水题,没有过多的花里胡哨,手算(不太建议)或者代码模拟即可

参考代码如下:

 1 #pragma GCC optimize(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 int n=2021, num = 0; 5 int main() 6 { 7     ios::sync_with_stdio(false); 8     for (register int i = 1; i <= 2021; i++) 9     {10         int num1=i;11         while (num1)12         {13             if (num1 % 10==6)num++;14             num1 /= 10;15         }16     }17     cout<<num;18     return 0;19 }

二:小明的作业;

不好意思,错了,我是弱鸡;

三:斐波那契(模拟思维的具体体现)

提供两种思路

1.常见的gcd写法,即gcd的递归写法,也有相应的辗转相除法,不在赘叙;

 1 #pragma GCC optimize(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 int a[100]={0,1,1}; 5 int b[100]; 6 long long  fenzi; 7 long long  fenmu; 8 long long  gcd(long long  a,long long  b)//手写gcd函数  9 {10     if(b==0) return a;11     return gcd(b,a%b);12 }13 int main()14 {15     for(register int i=3;i<=18;i++)16     {17         a[i]=a[i-1]+a[i-2];18     }19     for(int i=1;i<=13;i++)20     {21         b[i]=a[i]*a[i+1];//分母 22     }23     fenzi=1;//分子 24     fenmu=1;//分母 25     for(int i=2;i<=13;i++)26     {27         fenzi=fenzi*b[i]+1*fenmu;28         fenmu=fenmu*b[i];29         long long  temp=gcd(fenzi,fenmu);//两者的最大共约数 30         fenzi=fenzi/temp;//通分 ,不通分的后果就是程序不走或者直接爆 31         fenmu=fenmu/temp;//通分 32     } 33     cout<<fenzi<<"/"<<fenmu<<endl;34     return 0;35 } 

还要一种是关于STL库里好像是直接能写一种gcd函数,具体请看这篇https://blog.csdn.net/qq_44731019/article/details/109478391(转载),然后网上给出的代码思路也是和手写gcd大致的,这个相较于手写省去了很多麻烦,学到了;

摘自网上代码:

 1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 int main() 5 { 6     long long f[14]; 7     f[0]=1; 8     f[1]=1; 9     for(int i=2;i<=13;i++)10     {11         f[i]=f[i-1]+f[i-2];12     }13     long long up=1,down=1;14     for(int i=1;i<13;i++)15     {16         long long x=f[i]*f[i+1];17         long long k=__gcd(x,down);18         down*=(x/k);19         up=up*(x/k)+down/x;20     }21     long long k=__gcd(up,down);22     up/=k;23     down/=k;24     cout<<up<<'/'<<down<<endl;25     return 0;26 }

四:数列重组;

全排列肯定是少不了了,久违的next_permutation()肯定是要用的,

大体思路即是,在按照字典序的情况下,先判断是否升序还是降序,并且对他们进行标记,然后满足了三个开始重新标记,即进行下一轮的升序或者降序判断,并且在满足条件的时候加一

参考代码如下:

 1 #pragma GCC optimize(3)  2 #include<bits/stdc++.h>  3 using namespace std; 4 int a[20] = {2, 3, 3, 3, 5, 6, 6, 7, 7, 8}; 5 int ans;//放结果  6 int main(){ 7     ios::sync_with_stdio(false);  8     do{//next_permutaion()一般搭配do-while使用  9         bool flag1 = false, flag2 = false;//flag1表示之前是否出现递增,flag2表示之前是否出现递减10         int cnt = 0;//计数器 11         for(register int i = 0;i<9; i++){//为社么是小于9呢?因为有i+1,那这样最后一个会越界,然后结果减半 12             if(a[i + 1] > a[i]){13                 flag1 = true;14                 if(flag2){15                      cnt ++;16                     flag2 = false;17                      flag1 = false;//flag1也要,因为当出现分割点后每次要从新的起点开始算,不受之前的区间影响了18 19                 }20 21             }22             else if(a[i + 1] < a[i]){23                 flag2 = true;24                 if(flag1){25                     cnt ++;26                     flag1 = false;27                     flag2 = false;28                 }29 30             }31         }32         if(cnt <= 2) ans ++;33     }while(next_permutation(a, a + 10));//按字典序排序 34     cout << ans;35     return 0;36 }

五:三角形个数

妥妥的好题,模拟思维的具体体现,这个题我是最后才做的,刚开始确实没想到是等差数列;不过网上大多数人说用前缀和求,我是弱鸡,我不会(●ˇ?ˇ●)

具体思路:

其实是找倒三角和正三角的个数,很不好找的其实

如果三角形的边长是i

对于大三角形来说,如果正三角形是以1开始,到n-i+1结束的等差数列

而对于倒三角来说,是从1开始,到n-2i+1结束的;

 1 #pragma GCC optimizee(3) 2 #include<bits/stdc++.h> 3 using namespace std; 4 const long long  M=1e9+7; 5 int main() 6 { 7     ios::sync_with_stdio(false); 8     long long d=20210411,n; 9     long long sumz=0;  10     for(n=d;n>=1;n--)11         sumz=(sumz+n*(n+1)/2)%M;12     long long sumd=0;  13     for(n=d-1;n>=1;n-=2)14         sumd=(sumd+n*(n+1)/2)%M;15     printf("%lld\n",(sumz+sumd)%M);16     return 0;17 }

此外,本题特别鸣谢我身旁的zhy同学,如果他不和我说这个题是等差并且一直在坚持这个题,或许我就give up了;

六:字符串

没有什么特殊的技巧,值得注意的是关于如何接受空格符的问题,这里有两种方法:

1.getline函数:http://c.biancheng.net/view/1345.html(转载)

2.输入的正则用法:https://blog.csdn.net/weixin_43469047/article/details/83753526(转载);

不得不说长见识了

七:不会

八:友谊纽带

唉,bfs我是很不擅长的,主要是用太多了STL关于队列的操作,我当时都不知道怎么做出来的,并且我的代码和网上标准答案大相径庭,还是学习大佬的代码把

 1 /*1.这题一开始我读题目了,我以为的是把这些点全部连接起来所需要的最小边数; 2     于是我用了并查集,只过了两个点~ 3 2.后来发现题目是要求找出一个连通块里的任意两点的距离,也就是连通块的最大长度; 4     这样的话我们就可以用BFS暴力搜索所有节点,找出它们距其他节点的最远距离`的最大值`; 5     当一次广搜之后仍有节点未被访问的则说明该图不只有一个连通块,输出-1; 6 */ 7 #include<bits/stdc++.h> 8 using namespace std; 9 vector<int>G[2005];10 int vis[2005];11 int BFS(int x){12     memset(vis,0,sizeof(vis));13     queue<int>q;14     q.push(x);15     int ans=0;16     while(!q.empty()){17         int f=q.front();18         q.pop();19         ans=max(ans,vis[f]);20         for(int i=0;i<G[f].size();i++){21             int temp=G[f][i];22             if(vis[temp]==0){23                 vis[temp]=vis[f]+1;24                 q.push(temp);25             }26         }27     }28     return ans;29 }30 int main(){31     int n,m;32     cin>>n>>m;33     for(int i=0;i<m;i++){34         int a,b;35         cin>>a>>b;36         G[a].push_back(b);37         G[b].push_back(a);38     } 39     int ans=0;40     bool flag=true;41     for(int j=1;j<=n;j++){42         ans=max(ans,BFS(j));43         for(int i=1;i<=n;i++)44             if(vis[i]==0){45                 flag=false;break;46             }47     }48     if(flag)49     cout<<ans<<endl;50     else cout<<"-1"<<endl;51     return 0;52 }

转载自:https://blog.csdn.net/alpha_xia/article/details/115703564?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~OPENSEARCH~Rate-2.pc_relevant_antiscanv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~OPENSEARCH~Rate-2.pc_relevant_antiscanv2&utm_relevant_index=4;

九:传送门

这题我知道是克鲁斯卡尔啊,我没板子不会写,太难了,寒假的时候最小生成树就不会,主要是图论太难了;

十:最后一个小时的时光,我当时脑子已经一片混沌了,这题我没记错的话应该是直接爆搜了,毕竟我也没啥技巧了,只能搜了,唉;

思路是:枚举出每种获胜情况,并且用check函数检验

然后接下来就是搜了
利用dfs来搜接下来下的一步棋的所有情况
当x==10是结束条件,其实在某一定程度上很像2n皇后,但又不像;

难度较高,高级的思维模拟题,如果没有技巧建议深搜,毕竟搜可以混一部分的分数,运气好的话还可以过

 1 #pragma GCC optimize(3)  2 #include<bits/stdc++.h>  3 using namespace std; 4 int p[100]; 5 int n; 6 int ans; 7 int check(int u)//检查函数  8 { 9     if(p[0]+p[4]+p[8]==3*u||p[2]+p[4]+p[6]==3*u)10      return 1;11     if(p[0]+p[3]+p[6]==3*u||p[1]+p[4]+p[7]==3*u||p[2]+p[5]+p[8]==3*u) 12     return 1;13     if(p[0]+p[1]+p[2]==3*u||p[3]+p[4]+p[5]==3*u||p[6]+p[7]+p[8]==3*u) 14     return 1;15     else16     return 0;17 }18 int dfs(int x)//深搜 19 {20     if(x==10)//边界条件 21     {22         if(check(1)) return 1;//正常返回 23         if(check(-1)) return -1;//异常返回,此处也可以用bool判断 24         return 0; 25     }26     //开始模拟,怎么这么多模拟题 27     int t,lost=0,win=0,d=0;28     if(x&1) t=1;29     else t=-1;30     for(int i=0;i<9;i++)31     {32         if(p[i]==0)33         {34             p[i]=t;35             if(check(t)) win++;36             else37             {38                int p=dfs(x+1);39                 if(p==t)40                     win++;41                 else if(p==0) d++;42                 else lost++;43             }44             p[i]=0;45         }46     }47     if(win!=0) 48     return t;49     else if(d!=0) 50     return 0;51     else 52     return (-1*t);53 }54 int main()55 {56     ios::sync_with_stdio(false);57     int t;58     cin>>t;59     while(t--)60     {61         ans=0;62         memset(p,0,sizeof(p));63         cin>>n;64         for(int i=1;i<=n;i++)65         {66             int x,y;67             cin>>x>>y;68             x--;69             y--;70             if(i&1) p[x*3+y]=1;//按位与运算,取 2进制整数 i 的最低位,如果最低位是1 则得1,如果最低位是0 则得0。 奇数 i 的最低位 是1,偶数i 的最低位 是0。 71             else p[x*3+y]=-1;72         }   73     ans=dfs(n+1);74     if(ans==1) cout<<'X'<<endl;75     else if(ans==0)76         cout<<-1<<endl;77     else cout<<'O'<<endl;78     }79     return 0;80 }

总结:

通过这次模拟赛,很明确的是,对于难题,思维题,较难的模拟题,还有图论尤其是最小生成树方面还是有很多的不足

但是也得到了一些经验:做不出来或者没思路的时候搜也是一种不错的选择;

下一步加强搜索的优化和训练,学习一些自己在图论上知识的空缺,加强模拟题以及思维题的训练,即使难,多练,也会熟能生巧的;

道阻且长,兴则将至,戒骄戒躁,任重道远,早日成为自己想成为的人。

奔向远方,加油加油!

posted @ 2022-03-13 18:03 江上舟摇 阅读(4) 评论(0) 编辑 收藏 举报
回帖
    优雅殿下

    优雅殿下 (王者 段位)

    2018 积分 (2)粉丝 (47)源码

    小小码农,大大世界

     

    温馨提示

    亦奇源码

    最新会员