B - Square Filling
题意:给出一个01矩阵,每次刷新可以将矩阵B [i,j][i+1,j][i,j+1][i+1,j+1]的一个2×2的矩阵刷为1,问需要多少次操作(不要求找出最小操作)
题解:找到一个符合的就将0刷为1,最后比较两个矩阵是否相等,相等即可以刷出,否则输出-1.
#include <cstdio>
const int N = 60 ;
int maze[N][N] , a[N][N] ;
int ans[N*N][2] ;
int main(){
int n , m ;
scanf ("%d%d",&n,&m) ;
for (int i = 1 ; i <= n ; ++ i)
for (int j = 1 ; j <= m ; ++ j)
scanf ("%d",&maze[i][j]) ;
int cnt = 0 ;
for (int i = 1 ; i < n ; ++ i){
for (int j = 1 ; j < m ; ++ j){
if (maze[i][j] && maze[i+1][j] && maze[i][j+1] && maze[i+1][j+1]){
ans[cnt][0] = i , ans[cnt++][1] = j ;
a[i][j] = 1 , a[i+1][j] = 1 , a[i][j+1] = 1 , a[i+1][j+1] = 1 ;
}
}
}
for (int i = 1 ; i <= n ; ++ i)
for (int j = 1 ; j <= m ; ++ j){
if (maze[i][j] != a[i][j]){
printf ("-1\n") ;
return 0 ;
}
}
printf ("%d\n",cnt) ;
for (int i = 0 ; i < cnt ; ++ i)
printf ("%d %d\n",ans[i][0],ans[i][1]) ;
return 0 ;
}
CC - Gas Pipeline
题意:给出一串01字符串要求为1的地方铺的管子两米高,0的可铺1或0 ,外面一圈每单位耗费a元,高没单位耗费b元,求最小花费。
题解:用dp当为1时加上1的花费,并且dp[i][0]要设置为无穷表示不可选,还有要注意的是两端的高度为1
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std ;
typedef long long ll ;
const int N = 2e5 + 5 ;
const ll INF = 1e15 ;
ll dp[N][2] ;
int main(){
int t ;
cin >> t ;
while(t --){
ll n , a , b ;
cin >> n >> a >> b ;
string s ;
cin >> s ;
memset(dp,0,sizeof(dp)) ;
dp[0][0] = b , dp[0][1] = INF ;
ll cost = 0 ;
for (ll i = 1 ; i <= n ; ++ i){
if (s[i-1] == '0'){
dp[i][0] = min(dp[i-1][0]+a+b , dp[i-1][1]+b+2*a) ;
dp[i][1] = min(dp[i-1][0]+2*b+2*a , dp[i-1][1]+2*b+a) ;
}
else
dp[i][1] = dp[i-1][1] + 2*b + a , dp[i][0] = INF ;
}
cout << dp[n][0] << endl ;
}
return 0 ;
}
D - Number Of Permutations(容斥)
题意:求给出的二元序对x和y都不递减的排列数量。
还是看看大佬解说叭:→题解1 题解2
容斥:答案为总的排列数-(ai单调不减或者bi单调不减的排列数)+(ai,bi都单调不减的排列数)。
#include <cstdio>
#include <algorithm>
using namespace std ;
typedef long long ll ;
const int N = 3e5 + 100 ;
const ll MOD = 998244353 ;
ll fac[N] ;
struct node{
ll l , r ;
};
node num[N] ;
void init(int n){ //计算阶乘(总方案数)
fac[0] = 1 ;
for (int i = 1 ; i <= n ; ++ i)
fac[i] = fac[i-1]*i%MOD ;
}
bool cmp1(node a , node b){
return a.r < b.r ;
}
bool cmp2(node a , node b){
if (a.l == b.l) return a.r < b.r ;
return a.l < b.l ;
}
int main(){
int n ;
scanf ("%d",&n) ;
init(n) ;
for (int i = 1 ; i <= n ; ++ i)
scanf ("%lld%lld",&num[i].l,&num[i].r) ;
ll sum = fac[n] , res = 1 ;
sort(num+1,num+1+n,cmp2) ; //以l为第一为关键字升序排列
for (int i = 1 ; i <= n ; ++ i){
int j = i ;
//统计l不降的个数
while(j+1 <= n && num[j+1].l==num[j].l) ++ j ;
res = res*fac[j-i+1]%MOD ;
i = j ;
}
sum = (sum-res+MOD)%MOD ; //为了防止sum变成负数先加上mod再取余
sort(num+1,num+1+n,cmp1) ; //以r为关键字进行排序
res = 1 ;
for (int i = 1 ; i <= n ; ++ i){
int j = i ;
//统计r不降的个数
while(j+1 <= n && num[j+1].r == num[j].r) ++ j ;
res = res*fac[j-i+1]%MOD ;
i = j ;
}
sum = (sum-res+MOD)%MOD ;
sort(num+1,num+1+n,cmp2) ;
bool flag = true ;
for (int i = 2 ; i <= n ; ++ i){
if (num[i].r < num[i-1].r){
flag = false ;
break ;
}
}
res = 1 ;
if (flag){
for (int i = 1 ; i <= n ; ++ i){
int j = i ;
//统计l和r同时不降的个数
while(j+1 <= n && num[j+1].l==num[j].l && num[j+1].r==num[j].r)
++ j ;
res = res*fac[j-i+1]%MOD ;
i = j ;
}
sum = (sum+res)%MOD ;
}
printf ("%lld\n",sum) ;
return 0 ;
}