A. Suborrays
直接从小到大或从大到小输出即可。
#include<bits/stdc++.h>
using namespace std;
int t, n;
int main(){
scanf("%d", &t);
while(t--){
scanf("%d", &n);
for(int i=n; i>0; i--) printf("%d ", i);
printf("\n");
}
return 0;
}
B. Fix You
除第n行和第m列格子外,其余格子中的物品最终都会被运输到第n行或第m列的格子中,所以只要保证第n行的格子中的物品能一直向右运输,第m列格子的物品能一直向下运输,就可以保证所有物品最终被运输到(n, m)格子。
#include<bits/stdc++.h>
using namespace std;
const int MAX = 100+5;
char a[MAX][MAX];
int t, n, m, ans;
int main(){
scanf("%d", &t);
while(t--){
ans = 0;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++){
scanf("%s", a[i]+1);
}
for(int i=1; i<n; i++){
if(a[i][m]=='R') ans++;
}
for(int i=1; i<m; i++){
if(a[n][i]=='D') ans++;
}
printf("%d\n", ans);
}
return 0;
}
C. Cyclic Permutations
对于序列中的任意一个数,如果它的两侧均有大于a的元素,那么必然会形成环。反之,如果将比元素a大的数全部安排在同一侧,就不会出现环。因为元素a序列中任意一个元素,所以要保证“比元素a大的数全部在同一侧”,就需要将除n以外(因为没有比n还大的元素)的(n-1)个数从小到大放置在元素n的两侧,并且每次放置只能放置在序列的两端的位置上(这样才能保证比a大的数在同一侧),这样一共有2(n-1) 种序列,这是不出现环的序列个数,总的序列个数为n!,那么有环的序列就是n!-2(n-1)种。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
int n;
ll ans;
ll pow(int n){
ll tmp;
if(n==1) return 2;
tmp = pow(n/2)%mod;
if(n%2==0) return (tmp*tmp)%mod;
else return (tmp*tmp*2)%mod;
}
int main(){
scanf("%d", &n);
ans = 1;
for(int i=2; i<=n; i++){
ans = (i*ans)%mod;
}
printf("%lld", (ans+mod-pow(n-1))%mod);
return 0;
}
D. 505
- 因为m≥n,当n≥4时,必定存在四个2 * 2的矩阵可以组成一个4 * 4的矩阵,如果2 * 2的矩阵满足条件,那么很显然4 * 4的矩阵一定是不满足条件的。所以n≥4时无解。
- 当n=1时,不存在偶数阶的矩阵,默认是good,答案就是0。
- 当n=2或n=3时,通过枚举第一列的状态,并通过第一列的状态构造符合条件的矩阵,在构造中获得每一种状态下修改的次数,取最小值即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 1e6+5;
int two[4][2]={{0,0}, {0,1}, {1,0}, {1,1}}; //n==2时,第一列的四种状态
int thr[8][3]={{0,0,0}, {0,0,1}, {0,1,0}, {0,1,1}, {1,0,0}, {1,0,1}, {1,1,0}, {1,1,1}}; //n==3时,第一列的8种状态
int n, m, ans;
int a[5][MAX], t[5][MAX];
char tmp[MAX];
int main(){
scanf("%d%d", &n, &m);
if(n>=4){ //n>=4,无解
ans = -1;
for(int i=0; i<n; i++) scanf("%s", tmp);
}
else{
for(int i=0; i<n; i++){
scanf("%s", tmp);
for(int j=0; j<m; j++){
a[i][j] = tmp[j]-'0';
}
}
if(n==1) ans = 0; //n==1, good, ans=0
else{
if(n==2){ /n==2
ans = 1e9;
for(int i=0; i<4; i++){ //枚举四种状态
int cnt = 0;
t[0][0] = two[i][0];
t[1][0] = two[i][1]; //初始化第一列的状态
if(t[0][0]!=a[0][0]) cnt++;
if(t[1][0]!=a[1][0]) cnt++; //计数修改的次数
for(int j=1; j<m; j++){ //根据第一列的状态构建合法矩阵
t[0][j] = a[0][j];
t[1][j] = a[1][j]; //从原序列复制第j列的状态
//判断当前状态时候合法,合法则不做修改;不合法则进行修改,同时计数
int mat = t[0][j] + t[1][j] + t[0][j-1] + t[1][j-1];
if(mat%2==0){
t[0][j] = (t[0][j]? 0:1); //因为j-1列已经使j-1列以前的满足条件了,不能再更改,所以只能改j列
cnt++;
}
}
ans = min(ans, cnt);
}
}
else{
ans = 1e9;
for(int i=0; i<8; i++){
int cnt = 0;
t[0][0] = thr[i][0];
t[1][0] = thr[i][1];
t[2][0] = thr[i][2];
if(t[0][0]!=a[0][0]) cnt++;
if(t[1][0]!=a[1][0]) cnt++;
if(t[2][0]!=a[2][0]) cnt++;
for(int j=1; j<m; j++){
t[0][j] = a[0][j];
t[1][j] = a[1][j];
t[2][j] = a[2][j];
int matu = t[0][j] + t[1][j] + t[0][j-1] + t[1][j-1];
int matd = t[1][j] + t[2][j] + t[1][j-1] + t[2][j-1];
if(matu%2 && matd%2) continue; //上下两个子矩阵均合法
if(matd%2){ //上面矩阵不合法,修改[0][j]
t[0][j] = (t[0][j]? 0:1);
cnt++;
}
else if(matu%2){ //下面矩阵不合法,修改[2][j]
t[2][j] = (t[2][j]? 0:1);
cnt++;
}
else{ //两个矩阵都不合法,修改两个矩阵的交点[1][j]
t[1][j] = (t[1][j]? 0:1);
cnt++;
}
}
ans = min(ans, cnt);
}
}
}
}
printf("%d", ans);
return 0;
}