给出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:签到好难。。
思路:(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&&hn+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]]=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::vectord(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<
os:一开始队友写的暴力,很容易就T了一发,,不打这种比较正式难度的比赛不知道,一打发现原来签到的知识点都没学全呜呜呜
给出一个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>t;
while(t--){
std::cin>>n>>m;
for(int i=0;i>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;
}
补不动了,就这样吧