Codeforces Round #748 (Div. 3) A~E 題解
阿新 • • 發佈:2021-10-15
本場連結:Codeforces Round #748 (Div. 3)
A. Elections
直接按題意模擬即可
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define forn(i,x,n) for(int i = x;i <= n;++i) #define forr(i,x,n) for(int i = n;i >= x;--i) #define OverJoy ios::sync_with_stdio(0),cin.tie(0); #define x first #define y second int main() { int T;scanf("%d",&T); while(T--) { int a,b,c;scanf("%d%d%d",&a,&b,&c); if(max(b,c) >= a) printf("%d ",max(b,c) - a + 1);else printf("%d ",0); if(max(a,c) >= b) printf("%d ",max(a,c) - b + 1);else printf("%d ",0); if(max(a,b) >= c) printf("%d ",max(a,b) - c + 1);else printf("%d ",0); puts(""); } return 0; }
B. Make it Divisible by 25
列舉一下25的倍數:25,50,75,100,125,150....可以發現 25 的倍數總是以 00 25 50 75 這四種結尾。直接列舉找出即可。
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define forn(i,x,n) for(int i = x;i <= n;++i) #define forr(i,x,n) for(int i = n;i >= x;--i) #define OverJoy ios::sync_with_stdio(0),cin.tie(0); #define x first #define y second const int N = 20; const char* OP[] = {"00","25","50","75"}; char s[N]; int main() { int T;scanf("%d",&T); while(T--) { scanf("%s",s + 1);int n = strlen(s + 1); int res = 1e9; forn(_,0,3) { forn(i,1,n) { if(s[i] != OP[_][0]) continue; forn(j,i + 1,n) if(s[j] == OP[_][1]) res = min(res,n - i - 1); } } printf("%d\n",res); } return 0; }
C. Save More Mice
可以想到:因為每次只能讓一個老鼠動,所以最好的辦法就是先找到最遠的老鼠送過去,如此將所有老鼠的位置排序,每次看最後一個老鼠有沒有被抓到,沒有的話因為老鼠總先動,所以必然能把它送過去,再更新貓的位置繼續即可。
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define forn(i,x,n) for(int i = x;i <= n;++i) #define forr(i,x,n) for(int i = n;i >= x;--i) #define OverJoy ios::sync_with_stdio(0),cin.tie(0); #define x first #define y second const int N = 4e5+7; int a[N]; int main() { int T;scanf("%d",&T); while(T--) { int n,k;scanf("%d%d",&n,&k); forn(i,1,k) scanf("%d",&a[i]); sort(a + 1,a + k + 1); int cur = 0,res = 0; forr(i,1,k) { if(a[i] > cur) ++res,cur += n - a[i]; else break; } printf("%d\n",res); } return 0; }
D1. All are Same
先考慮無解:當所有的數一開始就相同的時候無解,因為這些數怎麼選 \(k\) 都可以。
其次,因為每個數都是去減若干倍的 \(k\) 所以對於一個可行的 \(k\),所有數關於 \(k\) 同餘。列舉 \(k\) 的取值找到最大合適的數即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define OverJoy ios::sync_with_stdio(0),cin.tie(0);
#define x first
#define y second
const int N = 2e6+7;
int a[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
forn(i,1,n) scanf("%d",&a[i]);
bool allsame = 1;
forn(i,1,n) if(a[i] != a[1]) allsame = 0;
if(allsame)
{
puts("-1");
continue;
}
int res = -1;
forn(k,1,2e6 + 1)
{
bool ok = 1;
int need = ((a[1] % k) + k) % k;
forn(i,1,n) if((a[i] % k + k) % k != need) ok = 0;
if(ok) res = max(res,k);
}
printf("%d\n",res);
}
return 0;
}
D2. Half of Same
同理,如果一開始就有至少一半的數相同,那麼無解。
由於 D1 做法的常數會因為 更多的修改 cnt 陣列導致超時。考慮更本質的做法:假如說有解的話,那麼必然會至少有一個數,在修改前盒修改後都沒有變化,因為如果所有的數都減了 \(k\) 的若干倍,那麼勢必可以同時少減一次 \(k\) 使得運算元變得更少,與題目要求運算元最少矛盾。所以必然存在某個數,前後都沒有變化。
那麼列舉每個數 \(a_j\) 作為目標值,所有的數最後都會變成 \(a_j\) 列舉某個 \(a_i\) 令 \(a_i - a_j\) 作為 \(k\)(注意 \(k \geq 1\))。而事實上,每個 \(k\) 的因數都是有可能的,所以直接把所有 \(k\) 的約數摳出來,最後找到最大且滿足條件的 \(k\) 即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define OverJoy ios::sync_with_stdio(0),cin.tie(0);
#define x first
#define y second
const int N = 2e6+7;
int a[N],cnt[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
forn(i,1,n) scanf("%d",&a[i]);
forn(i,1,n) ++cnt[a[i] + 1000000];
bool bad = 0;
forn(i,1,n) if(2 * cnt[a[i] + 1000000] >= n) bad = 1;
forn(i,1,n) --cnt[a[i] + 1000000];
if(bad)
{
puts("-1");
continue;
}
vector<int> st;
forn(i,1,n) forn(j,1,n) if(a[i] > a[j])
{
int k = a[i] - a[j];
for(int t = 1;t * t <= k;++t) if(k % t == 0) st.push_back(t),st.push_back(k / t);
}
int res = -1;
for(auto& k : st)
{
forn(i,1,n) ++cnt[(a[i] % k + k) % k];
bool ok = 0;
forn(i,1,n) if(2 * cnt[(a[i] % k + k) % k] >= n) ok = 1;
if(ok) res = max(res,k);
forn(i,1,n) --cnt[(a[i] % k + k) % k];
}
printf("%d\n",res);
}
return 0;
}
E. Gardener and Tree
就是拓撲排序,把點的度數定義為與他相連的邊的個數再按拓撲排序的方式逐層拆即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define OverJoy ios::sync_with_stdio(0),cin.tie(0);
#define x first
#define y second
const int N = 4e5+7;
vector<int> E[N];
int deg[N];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n,k;scanf("%d%d",&n,&k);
forn(i,1,n) E[i].clear(),deg[i] = 0;
forn(i,2,n)
{
int u,v;scanf("%d%d",&u,&v);
E[u].push_back(v);E[v].push_back(u);
++deg[u];++deg[v];
}
int res = n,step = 0;
queue<int> q,t;forn(i,1,n) if(deg[i] == 1) q.push(i);
while(step < k)
{
if(res <= 2)
{
res = 0;
break;
}
res -= q.size();
while(!q.empty())
{
int u = q.front();q.pop();
for(auto& v : E[u]) if(--deg[v] == 1) t.push(v);
}
q = t;t = queue<int>();
++step;
}
printf("%d\n",res);
}
return 0;
}