
给出A,B,C三个数,每次操作可以把B变为A-B,也可以将C变成B-C,给出x,问经过若干次操作之后能否使得C等于x。
思路:首先有一个性质可以知道,这个x一定是两种操作交替进行得来的因为如果一个操作连续做两次,相当于没有操作。这样我们可以倒着推:
在这里我们规定B'=A-B:




根据这些推导,可以知道此时满足条件:(C+x-B)%(B-B')==0,而因为第一步是先改变B的值还是先改变C的值不确定,所以另一种的满足条件即为:(C+x-B')%(B-B')==0。注意特判:当C==x时,不需要进行任何操作;如果A=2*B,即改变B的操作没有任何作用,此时只有B-C==x时才会满足条件。
AC Code:
- #include
-
- int t,A,B,C,x;
-
- int main(){
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cin>>t;
- while(t--){
- std::cin>>A>>B>>C>>x;
- int BB=A-B;
- if(C==x){
- std::cout<<"Yes"<<'\n';
- continue;
- }
- if(2*B==A&&B-C==x){
- std::cout<<"Yes"<<'\n';
- continue;
- }
- if(2*B==A){
- std::cout<<"No"<<'\n';
- continue;
- }
- if((C-x)%(BB-B)==0){
- std::cout<<"Yes"<<'\n';
- continue;
- }
- if((C+x-B)%(B-BB)==0||(C+x-BB)%(B-BB)==0){
- std::cout<<"Yes"<<'\n';
- continue;
- }
- std::cout<<"No"<<'\n';
- }
- return 0;
- }
os:签到好难。。

给出数字n,输出等比例的图像。
思路:(1)模拟,队友搞的,很强;(2)数据范围小于等于5,直接打表也很不错。
AC Code:
- #include
-
- int n;
-
- void N(int n,int h){
- if(h==1||h==2*n+3){
- for(int i=1;i<=2*n+3;i++){
- if(i==1||i==2*n+3) std::cout<<"@";
- else std::cout<<".";
- }
- }
- else{
- for(int i=1;i<=2*n+3;i++){
- if(i==1||i==2*n+3||i==h) std::cout<<"@";
- else std::cout<<".";
- }
- }
- }
- void F(int n,int h){
- if(h==1||h==n+2){
- for(int i=1;i<=2*n+3;i++)
- std::cout<<"@";
- }
- else{
- std::cout<<"@";
- for(int i=1;i<=2*n+2;i++)
- std::cout<<".";
- }
- }
- void L(int n,int h){
- if(h==2*n+3){
- for(int i=1;i<=2*n+3;i++)
- std::cout<<"@";
- }
- else{
- std::cout<<"@";
- for(int i=1;i<=2*n+2;i++)
- std::cout<<".";
- }
- }
-
- void S(int n,int h){
- if(h==1||h==2*n+3||h==n+2){
- for(int i=1;i<=2*n+3;i++)
- std::cout<<"@";
- }
- if(h>1&&h
2){ - std::cout<<"@";
- for(int i=1;i<=2*n+2;i++)
- std::cout<<".";
- }
- if(h>n+2&&h<2*n+3){
- for(int i=1;i<=2*n+2;i++)
- std::cout<<".";
- std::cout<<"@";
- }
- }
-
- int main(){
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cin>>n;
- for(int i=1;i<=13*n+19;i++)
- std::cout<<"*";
- std::cout<<'\n';
- for(int i=1;i<=n;i++)
- for(int j=1;j<=13*n+19;j++){
- if(j==1) std::cout<<"*";
- else if(j==13*n+19) std::cout<<"*"<<'\n';
- else std::cout<<".";
- }
- for(int i=1;i<=2*n+3;i++)
- {
- for(int j=1;j<=13*n+19;j++)
- {
- if(j==1) std::cout<<"*";
- else if(j==13*n+19) std::cout<<"*"<<'\n';
- else if(j==n+3)
- {
- N(n,i);
- for(int k=1;k<=n+1;k++)
- std::cout<<".";
- F(n,i);
- for(int k=1;k<=n+1;k++)
- std::cout<<".";
- L(n,i);
- for(int k=1;k<=n+1;k++)
- std::cout<<".";
- S(n,i);
- for(int k=1;k<=n+1;k++)
- std::cout<<".";
- j=13*n+18;
- }
- else std::cout<<".";
- }
- }
- for(int i=1;i<=n;i++)
- for(int j=1;j<=13*n+19;j++){
- if(j==1) std::cout<<"*";
- else if(j==13*n+19) std::cout<<"*"<<'\n';
- else std::cout<<".";
- }
- for(int i=1;i<=13*n+19;i++)
- std::cout<<"*";
- std::cout<<'\n';
- return 0;
- }

给定一棵树,每个点给出一个权值d[i],表示该位置向1走的这条路径中最多走d[i]步,问每个点可以由几个点到达。
思路:每个点可以向上走d[i]步,说明这一段每个点的结果都要+1,很显然是个差分问题,将O(n)转化为O(1)修改,然后最后一步DFS统计答案即可,基本是个树上点差分的板子题。
AC Code:
- #include
-
- #define int long long
- typedef long long ll;
- const int N=2e6+5;
- int n,cnt;
- int head[N],e[N<<1],next[N<<1],id[N],out[N];
- int deep[N],size[N],top[N],fa[N],son[N];
- int d[N],fat[N][30],f[N],w[N];
-
- void add_edge(int u,int v){
- e[cnt]=v;
- next[cnt]=head[u];
- head[u]=cnt++;
- }
-
- void DFS1(int u,int father){
- deep[u]=deep[father]+1;
- size[u]=1;
- fa[u]=father;
- for(int k=1;k<=25;k++){
- fat[u][k]=fat[fat[u][k-1]][k-1];
- }
- for(int i=head[u];~i;i=next[i]){
- int j=e[i];
- if(j==father) continue;
- fat[j][0]=u;
- DFS1(j,u);
- size[u]+=size[j];
- if(size[son[u]]
- }
- }
-
- void DFS2(int u,int father){
- f[u]=w[u];
- for(int i=head[u];~i;i=next[i]){
- int j=e[i];
- if(j==father) continue;
- DFS2(j,u);
- f[u]+=f[j];
- }
- }
-
- int LCA(int u,int depth){
- for(int k=25;k>=0;k--){
- if(deep[fat[u][k]]>=depth)
- u=fat[u][k];
- }
- return u;
- }
-
- signed main(){
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cin>>n;
- memset(head,-1,sizeof(head));
- for(int i=1;i<=n-1;i++){
- int u,v;
- std::cin>>u>>v;
- add_edge(u,v);
- add_edge(v,u);
- }
- DFS1(1,0);
- std::vector<int>d(n+5,0);
- for(int i=1;i<=n;i++){
- std::cin>>d[i];
- }
- for(int i=1;i<=n;i++){
- int tar=deep[i]-d[i];
- tar=std::max((int)1,tar);
- int t=LCA(i,tar);
- w[fa[t]]--;
- w[i]++;
- }
- DFS2(1,0);
- for(int i=1;i<=n;i++){
- std::cout<
" \n"[i==n]; - }
- return 0;
- }
os:一开始队友写的暴力,很容易就T了一发,,不打这种比较正式难度的比赛不知道,一打发现原来签到的知识点都没学全呜呜呜
Z-Game on Grid

给出一个n*m的棋盘,由'.','a','b'组成,走到a算Alice赢,走到b算Bob赢,走到(n,m)平局,每次每个人可以向右或者向下走一格,Alice先手,问是否有先手必胜,平局或者必输的策略。
思路:考虑DP。我也不知道为什么,感觉很怪。标解给的是记忆化搜索的做法。即倒着进行DP转移,我们在计算先手必胜时,设定A处值为1,B处为0,(n,m)处为0,根据到某一步是先手还是后手分类讨论,当到达(i,j)点且为先手操作时,只要(i+1,j)或者(i,.j+1)任意一个是先手必胜态则一定会胜;若当前为后手操作时,仅当(i,j+1)和(i+1,j)两点都为先手必胜态才会胜,即表示为符号:

其他两种情况类似考虑,只是设置不同的初始值即可。
题解写的很妙,它把状态表示成二进制,即题解中1,2,4分别表示001,010,100三种状态,这样类似状态压缩的方法可以学习。
AC Code:
- #include
-
- typedef long long ll;
- const int N=505;
- int t,n,m;
- char f[N][N][2];
- std::string s[N];
-
- int DFS(int x,int y,int u){
- if(s[x][y]=='A') return 1;
- if(s[x][y]=='B') return 4;
- if(x==n-1&&y==m-1) return f[x][y][u]=2;
- char &q=f[x][y][u];
- if(q==-1){
- if(u==0){
- q=0;
- if(x+1
DFS(x+1,y,u^1); - if(y+1
DFS(x,y+1,u^1); - }
- else{
- q=7;
- if(x+1
DFS(x+1,y,u^1); - if(y+1
DFS(x,y+1,u^1); - }
- }
- return q;
- }
-
- int main(){
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cin>>t;
- while(t--){
- std::cin>>n>>m;
- for(int i=0;i
- std::cin>>s[i];
- }
- memset(f,-1,sizeof(f));
- int ans=DFS(0,0,0);
- std::cout<<(ans&1?"yes":"no")<<' '<<(ans&2?"yes":"no")<<' '<<(ans&4?"yes":"no")<<'\n';
- }
- return 0;
- }
补不动了,就这样吧
-
相关阅读:
C++程序入门(helloworld.cpp编写)
layUI带搜索的选择框样式和官网显示不一致
重新定义商业——以用户为中心的全新商业模式
Android13适配-Google官方照片视频选择器
1186: 奖学金(结构体专题)
【Matlab】一、解常微分方程ODE
【学习笔记38】JavaScript中的本地存储
SpringBoot自动装配
企业精准拓客必不可少的利器丨快鲸scrm系统
面试阿里,倒在了第4轮后,才幡然醒悟——论系统学习的重要性
-
原文地址:https://blog.csdn.net/m0_62289613/article/details/126656074