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] << ' ';
}
}