6.2三道模拟
真的是太菜了...
题也不会做,策略也失误,对T2过于自信认为自己能A,结果T3看都没看...最后只拿100分
这个题应该拿250+的啊...
T1 https://www.luogu.org/problemnew/show/P4071
预处理组合数和错排直接回答就行
30mins(考试时)
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<climits> #include<ctime> #include<vector> #include<map> #include<queue> using namespace std; #define ll long long inline ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch >'9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int mod = 1e9 + 7; const int maxn = 1e6 + 10; ll power(ll a,ll b) { ll ans = 1,res = a; while(b) { if(b & 1) (ans *= res) %= mod; (res *= res) %= mod; b >>= 1; } return ans; } ll fac[maxn],inv[maxn]; ll n,m; ll ans; ll cal(ll n,ll m) { return fac[n] * inv[m] % mod * inv[n - m] % mod; } ll f[maxn]; int main() { ll t = read(); inv[0] = fac[0] = 1; for(int i = 1;i <= maxn - 10;i++) { fac[i] = fac[i - 1] * i % mod; inv[i] = power(fac[i],mod - 2); } f[1] = 0,f[2] = f[0] = 1; for(int i = 3;i <= maxn - 10;i++) f[i] = (i - 1) * (f[i - 1] + f[i - 2]) % mod; while(t--) { n = read(),m = read(); printf("%lld\n",cal(n,m) * f[n - m] % mod); } }
T2 https://www.luogu.org/problemnew/show/P2446
考虑到可以让无数个机器人同时出发,那么一个节点可以有两个dis值
分别是图上的最短路距离和实际到达的最早时间
然后你可以边dij边处理第二个值,当一个节点的所有保护城市都被访问过以后就把这个点塞进堆
爆零是因为更新dis的时候,想当然的按照传统dij用数组里的值更新,然而这道题应该拿实际时间更新,不然一边dij一边处理就失去意义了,还不如用拓扑排序
2.5h(考试 + 订正)
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; typedef long long ll; #define O(x) cout << #x << " " << x << endl; #define pii pair<ll,int> #define mp make_pair #define B cout << "breakpoint" << endl; inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int maxn = 3005; const int maxm = 70005; const ll inf = 99999999999; int n,m; struct egde { int to,next; ll cost; }e[maxm]; int fir[maxn],alloc; void adde(int u,int v,ll w) { e[++alloc].next = fir[u]; fir[u] = alloc; e[alloc].to = v; e[alloc].cost = w; } vector<int> l[maxn]; int cnt[maxn]; ll dis[maxn]; ll res[maxn]; bool vis[maxn]; void dij() { for(int i = 1;i <= n;i++) dis[i] = inf; priority_queue<pii,vector<pii>,greater<pii> > p; p.push(mp(0,1)); dis[1] = 0; while(p.size()) { pii t = p.top(); p.pop(); int u = t.second; //O(u); ll dist = t.first; if(vis[u]) continue; vis[u] = 1; for(int i = fir[u];i;i = e[i].next) { int v = e[i].to; ll w = e[i].cost; if(dis[v] > dist + w) { dis[v] = dist + w; if(cnt[v] == 0) p.push(mp(max(dis[v],res[v]),v)); } } for(int i = 0;i < l[u].size();i++) { int v = l[u][i]; //O(v); cnt[v]--; res[v] = max(res[v],dist); if(cnt[v] == 0) p.push(mp(max(dis[v],res[v]),v)); } } } int main() { //freopen("landcraft.in","r",stdin); //freopen("landcraft.out","w",stdout); n = read(),m = read(); for(int i = 1;i <= m;i++) { int u = read(),v = read(),w; scanf("%lld",&w); if(u == v) continue; adde(u,v,w); } for(int i = 1;i <= n;i++) { cnt[i] = read(); for(int j = 1;j <= cnt[i];j++) { int v = read(); l[v].push_back(i); } } dij(); printf("%lld",max(dis[n],res[n])); }
T3 https://www.luogu.org/problemnew/show/P3745
这么直白的题考试的时候应该多放时间的...确实是被T2扰乱视听了
不会三分,用个很直白的枚举做法
枚举最晚结束时间,你就可以算出在这个时间结束的时候的花费
O(nlogn),虽然比别的做法多个log,但是代码难度几乎是没有的,而且非常易懂,重要的是可以过
然后不要忘了,学生的不满意度应该是被加进花费的(根据定义)
1.0h(订正)
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<climits> #include<ctime> #include<vector> #include<map> #include<queue> using namespace std; typedef int mainint; #define int unsigned long long #define O(x) cout << #x << " " << x << endl; inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch >'9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int maxn = 1e5 + 5; int A,B,C; int n,m; int t[maxn],sumt[maxn];//希望时间 int b[maxn],sumb[maxn];//实际时间 int ans = LONG_LONG_MAX; mainint main() { A = read(),B = read(),C = read(); n = read(),m = read(); for(int i = 1;i <= n;i++) t[i] = read(); for(int i = 1;i <= m;i++) b[i] = read(); sort(t + 1,t + 1 + n); sort(b + 1,b + 1 + m); for(int i = 1;i <= n;i++) sumt[i] = sumt[i - 1] + t[i]; for(int i = 1;i <= m;i++) sumb[i] = sumb[i - 1] + b[i]; for(int i = min(t[1],b[1]);i <= max(t[n],b[m]);i++) { int tp = 0; int p1 = lower_bound(b + 1,b + 1 + m,i) - b;//b[p1] <= i的最大b[p1] while(b[p1] > i) p1--; int tp1 = p1 * i - sumb[p1],tp2 = sumb[m] - sumb[p1] - (m - p1) * i;//tp1:可以调的时间,tp2:实际需要调的时间 //O(i); O(tp1); O(tp2); if(A < B) { if(tp1 > tp2) tp += A * tp2; else tp += A * tp1 + B * (tp2 - tp1); } else tp += B * tp2; int tot = lower_bound(t + 1,t + 1 + n,i) - t; while(t[tot] > i) tot--;//t[tot] <= i 的最大t[tot] tp = tp + (tot * i - sumt[tot]) * C; ans = min(ans,tp); } cout << ans; }