2021牛客多校第二場
阿新 • • 發佈:2021-07-20
I - Penguins (模擬題)
直接bfs,時間複雜度O(20^4)
#include <bits/stdc++.h> #define endl '\n' #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0) #define mp make_pair #define seteps(N) fixed << setprecision(N) typedef long long ll; using namespace std; /*-----------------------------------------------------------------*/ ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} #define INF 0x3f3f3f3f const int N = 25; const double eps = 1e-5; bool vis[N][N][N][N]; char a[N][N], b[N][N]; int fx[4][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1} }; int fxidl[4] = {2, 1, 0, 3}; int fxidr[4] = {2, 0, 1, 3}; bool check(int x,int y) { if(x <= 0 || x > 20 || y <= 0 || y > 20) return false; return true; } struct node { int x1, y1, x2, y2; }; node up[N][N][N][N]; int rfx[N][N][N][N]; char cfx[] = "DLRU"; bool bfs(int x1, int y1, int x2, int y2) { queue<node> q; q.push({x1, y1, x2, y2}); vis[x1][y1][x2][y2] = 1; while(!q.empty()) { node cur = q.front(); q.pop(); x1 = cur.x1, y1 = cur.y1, x2 = cur.x2, y2 = cur.y2; if(x1 == 20 && y1 == 1 && x2 == 1 && y2 == 1) { return true; } for(int i = 0; i < 4; i++) { int f1 = fxidl[i], f2 = fxidr[i]; int nx1 = x1 + fx[f1][0], ny1 = y1 + fx[f1][1]; int nx2 = x2 + fx[f2][0], ny2 = y2 + fx[f2][1]; if(!check(nx1, ny1) || a[ny1][nx1] == '#') {nx1 = x1, ny1 = y1;} if(!check(nx2, ny2) || b[ny2][nx2] == '#') {nx2 = x2, ny2 = y2;} if(vis[nx1][ny1][nx2][ny2]) continue; vis[nx1][ny1][nx2][ny2] = 1; q.push({nx1, ny1, nx2, ny2}); up[nx1][ny1][nx2][ny2] = cur; rfx[nx1][ny1][nx2][ny2] = i; } } return false; } int main() { IOS; for(int i = 1; i <= 20; i++) { for(int j = 1; j <= 20; j++) { cin >> a[i][j]; } for(int j = 1; j <= 20; j++) { cin >> b[i][j]; } } up[20][20][1][20] = {0, 0, 0, 0}; bfs(20, 20, 1, 20); vector<int> ans; int x1 = 20, y1 = 1, x2 = 1, y2 = 1; while(x1) { ans.push_back(rfx[x1][y1][x2][y2]); node u = up[x1][y1][x2][y2]; x1 = u.x1, y1 = u.y1, x2 = u.x2, y2 = u.y2; } ans.pop_back(); reverse(ans.begin(), ans.end()); cout << ans.size() << endl; for(int i = 0; i < ans.size(); i++) cout << cfx[ans[i]]; cout << endl; x1 = 20, y1 = 20, x2 = 1, y2 = 20; a[y1][x1] = 'A'; b[y2][x2] = 'A'; for(int i = 0; i < ans.size(); i++) { int f1 = fxidl[ans[i]], f2 = fxidr[ans[i]]; int nx1 = x1 + fx[f1][0], ny1 = y1 + fx[f1][1]; int nx2 = x2 + fx[f2][0], ny2 = y2 + fx[f2][1]; if(!check(nx1, ny1) || a[ny1][nx1] == '#') {nx1 = x1, ny1 = y1;} if(!check(nx2, ny2) || b[ny2][nx2] == '#') {nx2 = x2, ny2 = y2;} a[ny1][nx1] = 'A'; b[ny2][nx2] = 'A'; x1 = nx1, y1 = ny1, x2 = nx2, y2 = ny2; } for(int i = 1; i <= 20; i++) { for(int j = 1; j <= 20; j++) cout << a[i][j]; cout << " "; for(int j = 1; j <= 20; j++) cout << b[i][j]; cout << endl; } }
J - Product of GCDs(數學)
分別算每個質因子\(p^c\)的貢獻。設\(f_{p,c}\)代表陣列中至少包含\(p^c\)的數的個數,則取\(k\)個數的方案數就是\(C(f_{p,c},k)\)。從而可得取k個數的gcd恰好包含\(p^c\)的方案數數為\(C(f_{p,c},k)-C(f_{p,c+1},k)\)。故質因子\(p\)的貢獻的冪為
\[(C(f_{p,1},k)-C(f_{p,2},k))+2(C(f_{p,2},k)-C(f_{p,3},k))+...+c(C(f_{p,c},k)-C(f_{p,c+1},k))=\sum{C(f_{p,c},k)} \]注意上面的式子求出來的是冪,要模\(\varphi(P)\)
__int128
避免使用快速乘。
這題比較卡常,要注意寫法。
時間複雜度:
分解質因數暴力求\(\varphi(P)\),預處理\(\sqrt{P}\)內的質數,複雜度為\(O(\sqrt{P}+T\frac{\sqrt{P}}{log P})\)
\(O(\frac{x}{logx})\)次快速冪(即素數個數,由\(\pi(x)\sim\frac{x}{logx}\)得到)
組合數\(O(nk)\)遞推
統計答案大概是\(x\log x\)級別的。
#include <bits/stdc++.h> #define endl '\n' #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0) #define mp make_pair #define seteps(N) fixed << setprecision(N) typedef long long ll; using namespace std; /*-----------------------------------------------------------------*/ ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} #define INF 0x3f3f3f3f const int N = 8e4 + 10; const int M = 1e7 + 10; const double eps = 1e-5; int pri[M], cnt; bool isnp[M]; int num[N]; ll C[40001][31]; ll getphi(ll n) { ll p = n; for(int i = 0; 1ll * pri[i] * pri[i] < p; i++) { if(n % pri[i] == 0) { p = p / pri[i] * (pri[i] - 1); while(n % pri[i] == 0) n /= pri[i]; } } if(n > 1) p = p / n * (n - 1); return p; } ll mul(ll x, ll y, ll m) { return (__int128)x * y % m; } inline ll qpow(ll a, ll b, ll m) { ll res = 1; while(b) { if(b & 1) res = mul(res, a, m); a = mul(a, a, m); b = b >> 1; } return res; } int main() { IOS; isnp[1] = 1; for(int i = 2; i < M; i++) { if(!isnp[i]) { pri[cnt++] = i; } for(int j = 0; j < cnt && 1ll * pri[j] * i < M; j++) { isnp[i * pri[j]] = 1; if(i % pri[j] == 0) break; } } int t; cin >> t; while(t--) { memset(num, 0, sizeof num); int n, k; ll P; cin >> n >> k >> P; ll phi = getphi(P); for(int i = 1; i <= n; i++) C[i][0] = 1; C[1][1] = 1; for(int i = 2; i <= n; i++) { for(int j = 1; j <= min(k, i); j++) { C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % phi; } } ll ans = 1; for(int i = 1; i <= n; i++) { int x; cin >> x; num[x]++; } for(int i = 0; i < cnt; i++) { int p = pri[i]; if(p > N) break; ll pow = 0; for(int j = p; j < N; j = j * p) { int c = 0; for(int x = j; x < N; x += j) { c += num[x]; } if(c < k) break; pow += C[c][k]; pow %= phi; if(1ll * j * p >= N) break; } if(pow) { ans = mul(qpow(p, pow, P), ans, P); } } cout << (ll)ans << endl; } }
K - Stack (構造)
使用二元組(var,id),其中var從1開始遞增,代表陣列b的值;id從n開始遞減。當陣列b沒有值時,var遞增、id遞減,然後將二元組插入棧中;當陣列b的值為x時,一直彈棧到彈出的二元組var==x,此時令彈出的二元組的id修改為當前的id,將當前的id修改為x,重新插入棧中。
可以發現過程中插入的二元組始終滿足題目要求。最後將二元組以var為第一關鍵字,id為第二關鍵字排序編號,就可以得到陣列a了。
#include <bits/stdc++.h>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f
const int N = 3e6 + 10;
const double eps = 1e-5;
typedef long long ll;
typedef pair<int, int> PII;
int b[N];
vector<PII> ans;
int res[N];
int pos[N];
bool cmp(int a, int b) {
return ans[a - 1] < ans[b - 1];
}
int main() {
IOS;
int t;
// cin >> t;
t = 1;
while(t--) {
ans.clear();
stack<PII> st;
int n, k;
cin >> n >> k;
for(int i = 1; i <= n; i++) b[i] = 0;
bool ok = true;
for(int i = 1; i <= k; i++) {
int p, x;
cin >> p >> x;
b[p] = x;
if(x <= 0) ok = false;
}
int id = n + 1;
int val = 0;
for(int i = 1; i <= n; i++) {
pos[i] = i;
if(b[i] && st.size() + 1 < b[i]) {
ok = false;
break;
} else {
id--;
if(b[i])
val = b[i];
else
val++;
PII pi{val, id};
while(!st.empty() && st.top() > pi) st.pop();
st.push(pi);
ans.push_back(pi);
// cout << pi.first << " " << pi.second << endl;
}
}
if(ok) {
sort(pos + 1, pos + 1 + n, cmp);
for(int i = 1; i <= n; i++) {
res[pos[i]] = i;
}
for(int i = 1; i <= n; i++)
cout << res[i] << " \n"[i == n];
} else
cout << -1 << endl;
}
}