2023牛客第三场补题报告A B D H J

2023牛客第三场补题报告A B D H J

A-World Fragments I_2023牛客暑期多校训练营3 (nowcoder.com)

思路

就是二进制转十进制然后求差,注意起始是否为0,是0就不行。

代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;
int a[N];

int f(string s) {
  int res = 0;
  for (int i = 0; s[i]; i++) {
    res *= 2;
    if (s[i] == '1') res++;
  }
  return res;
}

void solve() {
  string s1, s2;
  cin >> s1 >> s2;
  if (f(s1) == 0) {
    if (f(s2) == 0) {
      cout << 0 << "\n";
    } else
      cout << -1 << "\n";
  } else
    cout << abs(f(s1) - f(s2)) << "\n";
}

signed main() {
  IOS;
  int t = 1;
  // cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}

B-Auspiciousness_2023牛客暑期多校训练营3 (nowcoder.com)

思路

观察数据范围,手玩了一下发现推公式不太行,考虑三维的dp,发现可做,但是状态比较难想。

代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 610;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, m, c[N][N], dp[N][N][2], fact[N];
void solve() {
  cin >> n >> m;
  fact[0] = 1;
  for (int i = 1; i <= 2 * n; i++) fact[i] = fact[i - 1] * i % m;
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= i; j++) {
      if (!j)
        c[i][j] = 1;
      else
        c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % m;
    }
  }
  for (int i = 0; i <= n; i++)
    for (int j = 0; j <= n; j++) dp[i][j][0] = dp[i][j][1] = 0;
  dp[0][0][0] = dp[0][0][1] = 1;
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= n; j++) {
      for (int k = 1; k <= i; k++)
        dp[i][j][0] = (dp[i][j][0] + dp[i - k][j][1] * c[n - i + k][k] % m) % m;
      for (int k = 1; k <= j; k++)
        dp[i][j][1] = (dp[i][j][1] + dp[i][j - k][0] * c[n - j + k][k] % m) % m;
    }
  }
  int ans = 0;
  for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= n; j++) {
      for (int k = 2; k <= n - j; k++)
        ans = (ans + dp[i][j][0] * (k - 1) % m * (i + j + k) % m * c[n - j][k] %
                         m * fact[2 * n - i - j - k] % m) %
              m; 
      for (int k = 2; k <= n - i; k++)
        ans = (ans + dp[i][j][1] * (k - 1) % m * (i + j + k) % m * c[n - i][k] %
                         m * fact[2 * n - i - j - k] % m) %
              m; 
    }
  }
  for (int i = 0; i <= n; i++)
    ans = (ans + dp[n][i][0] * n % m + dp[i][n][1] * n % m) % m;
  cout << ans << '\n';
}

signed main() {
  IOS;
  int t = 1;
  cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}

D-Ama no Jaku_2023牛客暑期多校训练营3 (nowcoder.com)

思路

手推一下就会发现,其实题目就是求给定一个01矩阵,将其变为全0/全1的最小操作次数,直接模拟即可。

代码

#include <bits/stdc++.h>
#define int long long
#define LL long long
//#define endl '\n'
#define P pair<int,int>
#define FOR(i,n) for(int i = 1;i <= n;i ++)  

using namespace std;
 
const int N = 2000 + 10;
const int mod = 998244353;
int n,m,k,x,y,b[N];
char c[N][N],d[N][N],s;

void solve() {
	cin >> n;
	for(int i = 1;i <= n;i ++) {
		for(int j = 1;j <= n;j ++) {
			cin >> c[i][j];
			d[i][j] = c[i][j];
		}
	}
	int ans = 0;
	// 1
	{
		for(int i = 1;i <= n;i ++) {
			if(c[1][i] != '1') {
				ans ++;
				for(int j = 1;j <= n;j ++) {
					if(c[j][i] == '0') c[j][i] = '1';
					else c[j][i] = '0';
				}
			}
		}
		for(int i = 2;i <= n;i ++) {
			int tmp = 0;
			for(int j = 1;j <= n;j ++)
			tmp += c[i][j] - '0';
			if(tmp == 0) ans ++;
			else if(tmp == n) continue;
			else ans = -mod;
		}
	}
	// 1
	for(int i = 1;i <= n;i ++) {
		for(int j = 1;j <= n;j ++) {
			c[i][j] = d[i][j];
		}
	}
	int ans2 = 0;
	{
		for(int i = 1;i <= n;i ++) {
			if(c[1][i] != '0') {
				ans2 ++;
				for(int j = 1;j <= n;j ++) {
					if(c[j][i] == '0') c[j][i] = '1';
					else c[j][i] = '0';
				}
			}
		}
		for(int i = 2;i <= n;i ++) {
			int tmp = 0;
			for(int j = 1;j <= n;j ++)
			tmp += c[i][j] - '0';
			if(tmp == 0) ans2 ++;
			else if(tmp == n) continue;
			else ans2 = -mod;
		}
	}
	ans2++;
	if(ans < 0 && ans2 < 0) ans = -1;
	else if(ans < 0) ans = ans2;
	else if(ans2 < 0);
	else ans = min(ans,ans2);
	for(int i = 1;i <= n;i ++) {
		for(int j = 1;j <= n;j ++) {
			c[i][j] = d[i][j];
		}
	}
	// 0
	int ans1 = 0;
	{
		for(int i = 1;i <= n;i ++) {
			if(d[1][i] != '0') {
				ans1 ++;
				for(int j = 1;j <= n;j ++) {
					if(d[j][i] == '0') d[j][i] = '1';
					else d[j][i] = '0';
				}
			}
		}
		for(int i = 2;i <= n;i ++) {
			int tmp = 0;
			for(int j = 1;j <= n;j ++)
			tmp += d[i][j] - '0';
			if(tmp == 0) continue;
			else if(tmp == n) ans1++;
			else ans1 = -mod;
		}
	}
	for(int i = 1;i <= n;i ++) {
		for(int j = 1;j <= n;j ++) {
			d[i][j] = c[i][j];
		}
	}
	int ans3 = 0;
	{
		for(int i = 1;i <= n;i ++) {
			if(d[1][i] != '1') {
				ans3 ++;
				for(int j = 1;j <= n;j ++) {
					if(d[j][i] == '0') d[j][i] = '1';
					else d[j][i] = '0';
				}
			}
		}
		for(int i = 2;i <= n;i ++) {
			int tmp = 0;
			for(int j = 1;j <= n;j ++)
			tmp += d[i][j] - '0';
			if(tmp == 0) continue;
			else if(tmp == n) ans3++;
			else ans3 = -mod;
		}
	}
	ans3++;
	if(ans1 < 0 && ans3 < 0) ans1 = -1;
	else if(ans1 < 0) ans1 = ans3;
	else if(ans3 < 0);
	else ans1 = min(ans1,ans3);
	
	if(ans < 0 && ans1 < 0) cout << -1;
	else if (ans < 0) cout << ans1;
	else if (ans1 < 0) cout << ans;
	else cout << min(ans1,ans);
}

signed main() {
    ios_base::sync_with_stdio(0),cin.tie(0);
    //freopen("in.txt", "r", stdin);
    int t = 1; 
    //cin >> t;
    while(t--) solve(); 
    return 0;
}

H-Until the Blue Moon Rises_2023牛客暑期多校训练营3 (nowcoder.com)

思路

观察到和不变,就是要求构造出来n个质数,其和为给定值,直接用哥德巴赫猜想构造,如果和为奇数,给一个3再给n-3个2,剩下的一定能构造出来;偶数直接构造n-2个2,剩下也能构造出来,所以就是判断和是不是大于给定值,注意的点就是特判n在1,2时候的情况。

代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second

using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;
int a[N];

void solve() {
  cin >> n;
  int sum = 0;
  for (int i = 1; i <= n; i++) cin >> a[i], sum += a[i];
  if (n == 1) {
    for (int i = 2; i * i <= a[1]; i++) {
      if (a[1] % i == 0) {
        cout << "No\n";
        return;
      }
    }
    if (a[1] != 1)
      cout << "Yes\n";
    else
      cout << "No\n";
  } else if (sum % 2) {
    if (n == 2) {
      sum -= 2;
      for (int i = 2; i * i <= sum; i++) {
        if (sum % i == 0) {
          cout << "No\n";
          return;
        }
      }
      if (sum != 1)
        cout << "Yes\n";
      else
        cout << "No\n";
    } else if (sum >= 2 * n + 1) {
      cout << "Yes\n";
    } else
      cout << "No\n";
  } else {
    if (sum >= 2 * n) {
      cout << "Yes\n";
    } else
      cout << "No\n";
  }
}

signed main() {
  IOS;
  int t = 1;
  // cin >> t;
  for (int i = 1; i <= t; i++) {
    solve();
  }
}

J-Fine Logic_2023牛客暑期多校训练营3 (nowcoder.com)

思路

观察到给定的有向图拆分后不能有环,有环一定需要两组,无环只需要一组,再用拓补排序跑一遍逆序对即可。

代码

#include <bits/stdc++.h>
using namespace std;
void solve();
int main(){
	//cin.sync_with_stdio(0);
	//cin.tie(0);
	int T = 1;
	//cin >> T;
	while(T--){
		solve();
	}
	return 0;
}
#define N 1000100
vector<int> g[N];
int d[N];
void solve(){
	int n, m;
	cin >> n >> m;
	for(int i = 0;i < m;i++){
		int u ,v;
		cin >> u >> v;
		g[u].push_back(v);
		d[v]++;
	}
	vector<int> ans;
	queue<int> q;
	for(int i = 1;i <= n;i++){
		if(d[i] == 0){
			q.push(i);
			ans.push_back(i);
		}
	}
	while(q.size()){
		int u = q.front();
		q.pop();
		for(int v:g[u]){
			d[v]--;
			if(d[v] == 0){
				ans.push_back(v);
				q.push(v);
			}
		}
	}
	for(int i = 1;i <= n;i++){
		if(d[i] != 0){
			cout << "2\n";
			for(int i = 1;i <= n;i++){
				cout << i << " ";
			}
			cout << "\n";
			for(int i = n;i >= 1;i--){
				cout << i << " ";
			}
			return;	
		}
	}
	cout << "1\n";
	for(int i = 0;i < n;i++){
		cout << ans[i] << ' ';
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值