白棋跟黑棋只能往上或往下走,如果有阻碍就无法通过
w到第一行的最小距离是s1
b到最后一行的距离是s2
s1 <= s2,那就是输出A
否则输出B
<span style="font-size:14px;">#include <bits/stdc++.h>
using namespace std;
char s[10][10];
int vw[10], vb[10];
int main()
{
memset(vw, 0, sizeof(vw));
memset(vb, 0, sizeof(vb));
int answ = 0, ansb = 0;
for(int i = 0; i < 8; i++)
{
scanf("%s", s[i]);
for(int j = 0; j < 8; j++)
{
if(s[i][j] == 'B') vw[j] = 1;
if(s[i][j] == 'W' && vw[j] == 0 && answ == 0) answ = i;
}
}
for(int i = 7; i >= 0; i--)
{
for(int j = 0; j < 8; j++)
{
if(s[i][j] == 'W') vb[j] = 1;
if(s[i][j] == 'B' && vb[j] == 0)
{
ansb=7-i;
break;
}
}
if(ansb > 0) break;
}
if(answ <= ansb) printf("A\n");
else printf("B\n");
return 0;
} </span>
【B. The Monster and the Squirrel】
正n变形,顶点顺时针标记为1~n,从1开始画对角线,如果在画一条对角线时要跟另一条对角线交叉,那么就不要延伸出去,与另一条对角线相交于一点就好
问你在这个正n变形里面有几块空间
通过画图找规律可以知道是(n-2)*(n-2)
W跟B这两个人走一步分别能走出w米跟b米
举个例子w=2,b=3,总长度l=7
当W走了3步到达6时,再走一步就要到8,>7,所以W最多走了6米
同理B最多也是走了6米
所以l=6是平局
求1<=x<=t中,平局的概率
用最简式表示
这实际上就是求w跟b的公倍数
公倍数~公倍数+min(w,b)这一段书都是可以的
还有一段就是1~min(w,b)
然后考虑临界点
<span style="font-size:14px;">#include <bits/stdc++.h>
using namespace std;
#define ll __int64
ll gcd(ll a, ll b)
{
ll res = 1;
while(res)
{
res = a%b;
a = b;
b = res;
}
return a;
}
int main()
{
ll t, w, b;
scanf("%I64d%I64d%I64d", &t, &w, &b);
ll ai = min(w, b);
ll ans;
if(t < ai) ans = t;
else
{
ans = ai - 1;
ll bi = max(w, b);
ll G = gcd(w, b);
ll lo = w/G;
int s1 = 0, s2 = 0;
while(lo)
{
lo /= 10;
s1++;
}
lo = b;
while(lo)
{
lo /= 10;
s2++;
}
if(s1+s2 < 20 )
{
G = w/G*b;
ll p = t/G*G+ai;
if(p <= t) ans = ans + t/G*ai;
else ans = ans + (t/G-1)*ai + t - t/G*G + 1;
}
}
ll f = gcd(ans, t);
printf("%I64d/%I64d\n", ans/f, t/f);
return 0;
} </span>
树形dp
n个顶点,n-1条双向边
m个点是超人必须要去的点
问从m个点中任选一个点为起点,遍历所有的点最短的路程是多少
输出起点和路程,如果路程相同的起点有多个,输出数值最小的那个
m个点肯定是连成一棵树的,我们可以从第一个点开始,搜索
记录每个顶点到第一个点的距离,找出到第一个点距离最长的那个点,这个点就是这棵树的终点
从终点开始搜索,记录与终点距离最长的那个点以及距离sx
最终的最短的距离 = 这棵树的边数*2 - sx
最后还需要进一步确认记录的点数值是否是最小的
#include <bits/stdc++.h>
using namespace std;
#define inf 130000
vector<int>adj[inf];
int vis[inf];
int sizee[inf], dis[inf];
void dfs(int p, int u)
{
sizee[u] = 0;
if(vis[u]) sizee[u]=1;
for(int i = 0; i < adj[u].size(); i++)
{
int v = adj[u][i];
if(v!=p)
{
dis[v] = dis[u] + 1;
dfs(u, v);
sizee[u] += sizee[v];
}
}
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
adj[u].push_back(v);
adj[v].push_back(u);
}
memset(vis, 0, sizeof(vis));
for(int i = 0; i < m; i++)
{
int a;
scanf("%d", &a);
vis[a] = 1;
}
memset(dis, 0, sizeof(dis));
dfs(-1, 1);
int v = -1;
for(int i = 1; i <= n; i++)
{
if(vis[i] && (v==-1 || dis[i] > dis[v])) v = i;
}
memset(dis, 0, sizeof(dis));
dfs(-1, v);
int sum = 0, sx = 0;
for(int i = 1; i <= n; i++)
{
if(sizee[i] && m-sizee[i]>0) sum += 2;
if(vis[i]) sx = max(sx, dis[i]);
}
for(int i = 1; i <= n; i++)
{
if(sx==dis[i] && vis[i] && i<v) v = i;
}
printf("%d\n%d\n", v, sum-sx);
return 0;
}
【E. BCPC】
这一题就是求满足以下条件的有多少组
1、(r[i] - c) * (w[j] - d) > r(r[j] - c) * (w[i] - d)
2、(r[j] - c) * (w[k] - d) > r(r[k] - c) * (w[j] - d)
3、(r[k] - c) * (w[i] - d) > r(r[i] - c) * (w[k] - d)
(以下的r[ ]代表的就是减去c后的,w[ ]代表减去d后的)
r[i] * w[j] > r[j] * w[i] => r[i]/w[i] 和 r[j]/w[j]的大小关系 => 显然这大小关系跟w[ ]的正负有关
令x[i] = r[i]/w[i],接下来就是对w[ ]分类讨论
w[i] w[j] w[k]
1、+ + +
相应的x[ ]的大小就是xi > xj > xk > xi,显然不成立
2、- - -
相应的x[ ]就是xi > xj > xk > xi,也不成立
3、+ + -
能得到xi > xj && xj < xk && xk < xi,也就是xi > xk > xj
4、+ - -
得到xi < xj && xj > xk && xk <xi,也就是xj > xi > xk
根据上面的分类讨论,我们可以将wi分为正负分别放入两个容器里面 po放的是正的,ne放的是负的
还有一点要注意的就是w == 0的时候
通过简单的推理,我们可以知道对于第3种情况,只可能是xi对应的w=0,此时的r<0
第四种情况只能是xj对应的w=0,r>0
<span style="font-size:14px;">#include <bits/stdc++.h>
using namespace std;
#define inf 345678+10
#define ll __int64
vector<double>po, ne;
int r[inf], w[inf];
double p[inf];
int main()
{
int n, c, d;
scanf("%d%d%d", &n, &c, &d);
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &r[i], &w[i]);
r[i] -= c, w[i] -= d;
p[i] = r[i]*1.0/w[i];
}
for(int i = 1; i <= n; i++)
{
if(w[i] > 0) po.push_back(p[i]);
else if(w[i] < 0) ne.push_back(p[i]);
}
sort(po.begin(), po.end());
sort(ne.begin(), ne.end());
ll f = 0, s = 0;
for(int i = 0; i < po.size(); i++)
{
f += (lower_bound(ne.begin(), ne.end(), po[i]) - ne.begin());
}
for(int i = 0; i < ne.size() ;i++)
{
s += (lower_bound(po.begin(), po.end(), ne[i]) - po.begin());
}
ll ans = 0;
for(int i = 1; i <= n; i++)
{
if(w[i] > 0)
{
ans += (ll)(ne.end()-upper_bound(ne.begin(),ne.end(),p[i])) * (lower_bound(ne.begin(),ne.end(),p[i])-ne.begin());
}
else if(w[i] < 0)
{
ans += (ll)(po.end()-upper_bound(po.begin(),po.end(),p[i])) * (lower_bound(po.begin(),po.end(),p[i])-po.begin());
}
else
{
if(r[i] < 0) ans += f;
else ans += s;
}
}
printf("%I64d\n", ans);
return 0;
} </span>