====== A. Suborrays ====== 所有排列都可以。 #include #define ll long long #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair using namespace std; const int N=1e5+10; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++)printf("%d ",i); puts(""); } return 0; } \\ ====== B. Fix You ====== 只要使最下边的行全向右、最右边的列全向下即可。 #include #define ll long long #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair using namespace std; const int N=105; char s[N][N]; int main() { int t; scanf("%d",&t); while(t--) { int n,m,ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%s",s[i]+1); for(int i=1;i \\ ====== C. Cyclic Permutations ====== 长度为 $n$ 的排列,每个位置向前面、后面最近的大于它的数字连边,问有环的方案有多少种。 观察,发现没有环的排列是单峰的,单峰排列 $2^{n-1}$ 种(考虑最大值以外的数字放左边还是右边)。 #include #define ll long long #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair using namespace std; const int N=1e6+10; const ll mod=1e9+7; ll qpow(ll a,ll n){ll res=1;while(n){if(n&1)res=res*a%mod;a=a*a%mod,n>>=1;}return res;} int main() { int n;ll res=1; scanf("%d",&n); for(int i=1;i<=n;i++)res=res*i%mod; printf("%lld\n",(res-qpow(2,n-1)+mod)%mod); return 0; } \\ ====== D. 505 ====== 给出 $n\times m$ 的矩阵,要使所有长宽都为偶数的子矩阵 $1$ 的个数都是奇数最少改变多少位置的值。 首先如果 $n,m$ 都不小于 $4$ 是无解的。 $n$ 或 $m$ 为 $1$ 直接满足条件。可以讨论一下 $n,m$ 中有一个为 $2$ 或 $3$ 的情况,只需要让所有 $2\times2$ 子矩阵维持奇数 $1$ 即可。 $n\times2$ :考虑所有 $1\times2$ 长方形,肯定是奇偶交替排列,枚举第一个位置应该是奇数还是偶数即可。 $n\times3$ :对于一个 $1\times3$ 矩形,两个 $1\times2$ 部分有一个交叠,还是枚举第一个位置两个 $1\times2$ 各自的奇偶性,对于某个位置如果两个 $1\times2$ 都需改变只改变中间交叠的一格即可。 #include #define ll long long #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair using namespace std; const int N=1e6+10; char s[N]; int a[N][4],n,m,res=N; int pos(int x,int y){return (x-1)*m+y;} int main() { scanf("%d%d",&n,&m); if(n>=4&&m>=4){puts("-1");return 0;} if(n==1||m==1){puts("0");return 0;} if(m<4) for(int i=1;i<=n;i++) { scanf("%s",s+1); for(int j=1;j<=m;j++)a[i][j]=s[j]-'0'; } else { for(int i=1;i<=n;i++) { scanf("%s",s+1); for(int j=1;j<=m;j++)a[j][i]=s[j]-'0'; } swap(n,m); } if(m==2) { int cnt=0; for(int i=1,j=0;i<=n;i++,j^=1)if(((a[i][1]+a[i][2])&1)!=j)cnt++; res=min(res,cnt),cnt=0; for(int i=1,j=1;i<=n;i++,j^=1)if(((a[i][1]+a[i][2])&1)!=j)cnt++; res=min(res,cnt); printf("%d\n",res); } else if(m==3) { int cnt=0; for(int i=1,j=0,k=0;i<=n;i++,j^=1,k^=1) { if(((a[i][1]+a[i][2])&1)!=j)cnt++; else if(((a[i][2]+a[i][3])&1)!=k)cnt++; } res=min(res,cnt),cnt=0; for(int i=1,j=0,k=1;i<=n;i++,j^=1,k^=1) { if(((a[i][1]+a[i][2])&1)!=j)cnt++; else if(((a[i][2]+a[i][3])&1)!=k)cnt++; } res=min(res,cnt),cnt=0; for(int i=1,j=1,k=0;i<=n;i++,j^=1,k^=1) { if(((a[i][1]+a[i][2])&1)!=j)cnt++; else if(((a[i][2]+a[i][3])&1)!=k)cnt++; } res=min(res,cnt),cnt=0; for(int i=1,j=1,k=1;i<=n;i++,j^=1,k^=1) { if(((a[i][1]+a[i][2])&1)!=j)cnt++; else if(((a[i][2]+a[i][3])&1)!=k)cnt++; } res=min(res,cnt); printf("%d\n",res); } return 0; } \\ ====== E. Pairs of Pairs ====== 随便搞一个dfs树,如果有深度大于 $\lceil\frac n2\rceil$ 的点直接输出到根的这条链,如果无,可以对于每个深度值,将同深度的点两两配对,每个深度最多只有一个点未匹配,即未匹配的点数小于 $\lceil\frac n2\rceil$ 。 #include #define ll long long #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair using namespace std; const int N=5e5+10,M=1e6+10; vectorg[N]; int q,head[N],cnt,n,m,dep[N],pa[N],f,vis[N]; struct Node{int nxt,to;}edges[M*2]; void addedge(int u,int v){edges[++cnt]=Node{head[u],v},head[u]=cnt;} void dfs1(int u) { if(dep[u]+1>=q)f=u;else g[dep[u]].pb(u); vis[u]=1; for(int i=head[u];~i;i=edges[i].nxt) { int v=edges[i].to; if(vis[v])continue; dep[v]=dep[u]+1,pa[v]=u,dfs1(v); } } int main() { int t; scanf("%d",&t); while(t--) { cnt=-1,f=0; scanf("%d%d",&n,&m); q=ceil(n/2.0)+0.1; for(int i=0;i<=n;i++)head[i]=-1,vis[i]=0,vector().swap(g[i]); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); addedge(u,v),addedge(v,u); } dfs1(1); if(f) { puts("PATH"); printf("%d\n",dep[f]+1); while(f)printf("%d ",f),f=pa[f]; puts(""); } else { puts("PAIRING"); printf("%d\n",(q+1)/2); for(int i=0;i0;i++) for(int j=0;j+10;j+=2) printf("%d %d\n",g[i][j],g[i][j+1]),q-=2; } } return 0; } \\