A - Calandar.
题意:给两个日期,规定每年12个月,每月30天,已知第一个日期是星期几,求第二个日期是星期几;
分析:水题。
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mp make_pair
#define pb push_back
#define T int T;scanf("%d",&T);while(T--)
const ll mod=1e9+7;
int main(){
ll y1,y,m1,m,d1,d;
string s;
ll ans1,ans;
map<string,int> ss;
string sss[5]={"Monday","Tuesday","Wednesday","Thursday","Friday"};
string sss1[5]={"Friday","Thursday","Wednesday","Tuesday","Monday"};
ss["Monday"] = 0;
ss["Tuesday"] = 1;
ss["Wednesday"] = 2;
ss["Thursday"] = 3;
ss["Friday"] = 4;
T{
scanf("%lld %lld %lld", &y, &m, &d);
cin >> s;
scanf("%lld %lld %lld", &y1, &m1, &d1);
ans = y*360ll+m*30ll+d;
ans1 = y1*360ll+m1*30ll+d1;
if(ans1>=ans){
ans1 = (ans1 - ans + ss[s]) % 5;
cout << sss[ans1] << endl;
}else{
ans1 = (ans - ans1 + 4 - ss[s]) % 5;
cout << sss1[ans1] << endl;
}
}
return 0;
}
D - Game on a Graph.
题意:已知一个n个点,m条边的连通图,k个人,每个人有编号1或2表示队伍,按顺序每次没人删一条边,如果删去一条边之后图不连通,则该队输,输出赢的队伍的编号。
分析:n个点要连通至少n-1条边,所以可以删去m-n+1条边。取余人数即可
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mp make_pair
#define pb push_back
#define T int T;scanf("%d",&T);while(T--)
const ll mod=1e9+7;
int main(){
int k,n,m;
int u,v;
int ans;
string s;
T{
scanf("%d", &k);
cin >> s;
scanf("%d %d", &n, &m);
for(int i = 0; i < m; i ++)
scanf("%d %d", &u, &v);
ans =(m-n+1) % k;
if(s[ans]=='1') cout << 2 << endl;
else cout << 1 << endl;
}
return 0;
}
F - Stones in the Bucket.
题意:n堆石头,每堆a[i]个,每次可以拿去任意一堆的一个石头,或者把任意一堆的一个石头放到另一堆,求最少几次操作后使得每堆石头数相等。
分析:先求平均值,分别求出比平均值大的和小的石头数的和,取大值。
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mp make_pair
#define pb push_back
#define T int T;scanf("%d",&T);while(T--)
const ll mod=1e9+7;
int a[1000005];
int main(){
int n;
ll sum;
ll ans1,ans2;
ll ave;
T{
ans1 = ans2 = sum = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i ++){
scanf("%d", a+i);
sum += a[i];
}
ave = sum/n;
for(int i = 1; i <= n; i ++){
if(a[i]>=ave) ans1 += a[i]-ave;
else ans2 += ave-a[i];
}
printf("%lld\n", max(ans1,ans2));
}
return 0;
}
L - Median.
题意:n个数,m个关系,接下来m行,每行一个u和v表示第u个数大于第v个数,输出n个数,1表示当前位置的数可能为中位数,0表示不可能。
分析:建图,出现环就全为0. 否则就求出每个点的父亲和儿子个数,两周都小于等于n/2就可能为中位数,输出种没有出现过的数也可能为中位数.
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mp make_pair
#define pb push_back
#define T int T;scanf("%d",&T);while(T--)
const ll mod=1e9+7;
int n,m;
vector<int> g1[105];
vector<int> g2[105];
int child[105];
int father[105];
int in[105];
int vis1[105];
int vis[105];
int is(){
queue<int> q;
for(int i = 1; i <= n; i ++){
if(in[i]==0 && vis1[i]){
q.push(i);
}
}
while(!q.empty()){
int u = q.front();
q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(auto i : g1[u]){
in[i]--;
if(in[i]==0){
q.push(i);
}
}
}
for(int i = 1; i <= n; i ++){
if(vis1[i] && vis[i]==0){
return 1;
}
}
return 0;
}
int dfs1(int u){
if(vis[u]) return 0;
vis[u] = 1;
int sum = 1;
for(auto i : g1[u]){
sum += dfs1(i);
}
return sum;
}
int dfs2(int u){
if(vis[u]) return 0;
vis[u] = 1;
int sum = 1;
for(auto i : g2[u]){
sum += dfs2(i);
}
return sum;
}
int main(){
T{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i ++){
g1[i].clear();
g2[i].clear();
vis[i] = 0;
vis1[i] = 0;
in[i] = 0;
father[i] = 0;
child[i] = 0;
}
for(int i = 0; i < m; i ++){
int u,v;
scanf("%d %d", &u, &v);
in[v] ++;
vis1[v] = vis1[u] = 1;
g1[u].push_back(v);
g2[v].push_back(u);
}
if(is()){
for(int i = 1; i <= n; i ++)
printf("0");
puts("");
continue;
}
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
vis[j] = 0;
}
child[i] = dfs1(i) - 1;
for(int j = 1; j <= n; j ++){
vis[j] = 0;
}
father[i] = dfs2(i) - 1;
// printf("%d %d\n", child[i], father[i]);
}
for(int i = 1; i <= n; i ++){
// printf("%d %d\n", child[i], father[i]);
if(!vis1[i] || father[i]<=n/2 && child[i]<=n/2)
printf("1");
else printf("0");
}
puts("");
}
return 0;
}
M - Sekiro.
题意:已知n和k,每次n/2向上取整,求k次后n是多少。
分析:n最后必然为1.
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mp make_pair
#define pb push_back
#define T int T;scanf("%d",&T);while(T--)
const ll mod=1e9+7;
int main(){
T{
int n,k;
scanf("%d %d", &n, &k);
if(n==0){
printf("0\n");
continue;
}
for(int i = 1; i <= k; i ++){
n = ceil(n*1.0/2);
if(n==1) break;
}
printf("%d\n", n);
}
return 0;
}