A:判斷一下和是不是3的倍數,由於只加不減,所以還要判斷有沒有大於和的1/3。

1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 int T,a,b,c,n,x; 9 namespace io{ 10 il char nc(){ 11 static char buf[100000],*p1=buf,*p2=buf; 12 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 13 } 14 template <class I> 15 il void fr(I &num){ 16 num=0;register char c=nc();it p=1; 17 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 18 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 19 num*=p; 20 } 21 }; 22 using io :: fr; 23 int main(){ 24 fr(T); 25 while(T--){ 26 fr(a),fr(b),fr(c),fr(n); 27 if((a+b+c+n)%3){puts("NO");continue;} 28 x=(a+b+c+n)/3; 29 if(a>x||b>x||c>x){puts("NO");continue;} 30 puts("YES"); 31 } 32 return 0; 33 }
B:發現只能向上和向右。所以我們必須保證序列在兩維上非降。那么按照x,y升序排序,然后判斷一下對於這個點是否存在x比它的x小且y比它的y大,有就是無解。由於字典序要小,所以肯定先右“R”再上“U”。

1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 const int N=100005; 9 int T,n,lastx,lasty; 10 bool flag; 11 struct ky{ 12 int x,y; 13 }a[N]; 14 bool cmp(ky p,ky q){ 15 return p.x^q.x?p.x<q.x:p.y<q.y; 16 } 17 int main(){ 18 scanf("%d",&T);it i; 19 while(T--){ 20 scanf("%d",&n); 21 for(i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].y); 22 std::sort(a+1,a+1+n,cmp); 23 flag=0; 24 for(i=1;i<=n;++i) 25 if(a[i].x!=a[i-1].x&&a[i].y<a[i-1].y) flag=1,i=n+1; 26 if(flag){puts("NO");continue;} 27 lastx=0,lasty=0,puts("YES"); 28 for(i=1;i<=n;++i){ 29 for(it j=lastx;j<a[i].x;++j) putchar('R'); 30 for(it j=lasty;j<a[i].y;++j) putchar('U'); 31 lastx=a[i].x,lasty=a[i].y; 32 } 33 putchar('\n'); 34 } 35 return 0; 36 }
C:先在√n時間內算出n的因子個數,判斷是否有解,注意除去n的1與本身這兩個因子。在有解的情況下找出兩個小於√n的一個大於√n的(若有解肯定存在)即可。

1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 int T,a,b,c,n,x,ans1,ans2,ans3; 9 namespace io{ 10 il char nc(){ 11 static char buf[100000],*p1=buf,*p2=buf; 12 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 13 } 14 template <class I> 15 il void fr(I &num){ 16 num=0;register char c=nc();it p=1; 17 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 18 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 19 num*=p; 20 } 21 }; 22 using io :: fr; 23 int main(){ 24 fr(T);it i;register long long now=1; 25 while(T--){ 26 fr(n); 27 it x=n,cnt=0;now=1; 28 for(i=2;i*i<=x;++i) 29 if(!(x%i)){ 30 cnt=0; 31 while(!(x%i)) 32 x/=i,++cnt; 33 now*=(cnt+1ll); 34 } 35 if(x>1) now<<=1; 36 now-=2; 37 if(now<3){puts("NO");continue;} 38 x=n,cnt=0,ans1=ans2=0; 39 for(i=2;cnt<2&&i*i<=x;++i) 40 if(!(x%i)) 41 ++cnt,x/=i,cnt==1?ans1=i:(cnt==2?ans2=i:ans3=i); 42 if(cnt==2&&x>ans2&&ans2) 43 puts("YES"),printf("%d %d %d\n",ans1,ans2,x); 44 else puts("NO"); 45 } 46 return 0; 47 }
D:構建mod x的剩余系,每次找到這個剩余系里面最大的加上x即可。注意到最多進行n次操作,所以>=n的其實沒啥意義。然后怎么找第一個未出現過的元素:很顯然按照我的添加方法肯定每個數只出現一次。所以維護一個set,只要每次把出現過的刪掉,輸出s.begin()(第一個元素也就是最小的沒被刪掉的,即還沒出現的)即可。

1 #include<stdio.h> 2 #include<string.h> 3 #include<bitset> 4 #include<set> 5 #include<algorithm> 6 #define it register int 7 #define ct const int 8 #define il inline 9 using namespace std; 10 const int N=1000005; 11 int T,a,b,c,n,x,f[N],maxn; 12 set<int> s; 13 namespace io{ 14 il char nc(){ 15 static char buf[100000],*p1=buf,*p2=buf; 16 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 17 } 18 template <class I> 19 il void fr(I &num){ 20 num=0;register char c=nc();it p=1; 21 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 22 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 23 num*=p; 24 } 25 }; 26 using io :: fr; 27 bitset<N> vs; 28 int main(){ 29 fr(n),fr(x);it i,nowmax=-1,y;maxn=-1; 30 for(i=0;i<x;++i) f[i]=-1; 31 for(i=0;i<=n;++i) s.insert(i); 32 for(i=1;i<=n;++i){ 33 fr(y),y%=x; 34 f[y]==-1?f[y]=y:f[y]+=x; 35 if(f[y]<=400000) s.erase(f[y]); 36 printf("%d\n",*s.begin()); 37 } 38 return 0; 39 }
E:每一列互不相關,所以可以枚舉每一列單獨考慮。因為我們可以移動和重置,有的數可以移動但有的必須重置。假設x為第i行j列的數,如果(x+m-1)/m<=n&&x%m==j%m,說明x移動到最終矩陣中的位置的最小次數是(i-(x+m-1)/m+n)%n(+n再%n是為了處理負數)。所以我們把每個最小次數用桶記下來這個最小次數的出現次數,然后枚舉最小次數i,求這一列需要的最小次數ans=Min(ans,i+n-s[i]),然后把ans累計入答案。

1 #include<stdio.h> 2 #include<vector> 3 #include<algorithm> 4 #define it register int 5 #define ct const int 6 #define il inline 7 using namespace std; 8 const int N=200005; 9 vector<int> a[N]; 10 int s[N],o,n,m; 11 il int Min(ct p,ct q){return p<q?p:q;} 12 namespace io{ 13 il char nc(){ 14 static char buf[100000],*p1=buf,*p2=buf; 15 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 16 } 17 template <class I> 18 il void fr(I &num){ 19 num=0;register char c=nc();it p=1; 20 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 21 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 22 num*=p; 23 } 24 } 25 using io :: fr; 26 void solve(ct x){ 27 it i,ans=n; 28 for(i=0;i<=n;++i) s[i]=0; 29 for(i=1;i<=n;++i) 30 if(a[x][i]%m==x%m&&(a[x][i]+m-1)/m<=n) ++s[(i-(a[x][i]+m-1)/m+n)%n]; 31 for(i=0;i<=n;++i) ans=Min(ans,i+n-s[i]); 32 o+=ans; 33 } 34 int main(){ 35 fr(n),fr(m);it i,j,x; 36 for(i=1;i<=m;++i) a[i].push_back(0); 37 for(i=1;i<=n;++i) 38 for(j=1;j<=m;++j) 39 fr(x),a[j].push_back(x); 40 for(i=1;i<=m;++i) solve(i); 41 printf("%d",o); 42 return 0; 43 }
F:明明還剩00:01:06的時候交F可是沒交上去嗚嗚嗚。思路是先以1為根找出深度最大的mx1,再以mx1為根找出深度最大的mx2,然后沿着這條路把路上的點標記一下,再找到深度最大的mx3。每次找的時候ans++記錄路徑長度。由於x個點會有x-1條路,所以最后答案為ans-1.

1 #include<stdio.h> 2 #include<string.h> 3 #include<bitset> 4 #include<algorithm> 5 #define it register int 6 #define ct const int 7 #define il inline 8 using namespace std; 9 const int N=1000005; 10 int h[N],nxt[N],adj[N],fa[N],ans,mx1,mx2,mx3,u,v,n,m,t,id,d[N]; 11 bitset<N> vs; 12 namespace io{ 13 il char nc(){ 14 static char buf[100000],*p1=buf,*p2=buf; 15 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 16 } 17 template <class I> 18 il void fr(I &num){ 19 num=0;register char c=nc();it p=1; 20 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 21 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 22 num*=p; 23 } 24 } 25 using io :: fr; 26 il void dfs(ct x){ 27 d[x]=(vs[x]?1:d[fa[x]]+1); 28 for(it i=h[x],j;i;i=nxt[i]) 29 if((j=adj[i])!=fa[x]) 30 fa[j]=x,dfs(j); 31 } 32 il void add(){ 33 nxt[++t]=h[u],h[u]=t,adj[t]=v,nxt[++t]=h[v],h[v]=t,adj[t]=u; 34 } 35 int main(){ 36 fr(n);it i; 37 for(i=1;i<n;++i) fr(u),fr(v),add(); 38 dfs(1); 39 for(i=1;i<=n;++i){fa[i]=0;if(d[i]>d[mx1]) mx1=i;} 40 dfs(mx1); 41 for(i=1;i<=n;++i) if(d[i]>d[mx2]&&i!=mx1)mx2=i; 42 for(i=mx2;i;i=fa[i]) vs[i]=1,++ans; 43 dfs(mx1); 44 for(i=1;i<=n;++i) if(d[i]>d[mx3]&&i!=mx1&&i!=mx2)mx3=i; 45 for(i=mx3;!vs[i];i=fa[i]) vs[i]=1,++ans; 46 printf("%d\n%d %d %d",ans-1,mx1,mx2,mx3); 47 return 0; 48 }
由於博主已經意識模糊,所以可能會有一些紕漏,請大家指出,謝謝。
這次唯一的收獲大概就是一題沒掛,於是用大號刷高了小號的rating(霧
大號打Div3不能增加Rating了QAQ,但為了好看還是用小號去刷大號正確率,結果每次都是一遍A,然后提高了小號的Rating……