Codeforces 197

A

Problem description

在一个n*m的矩形上,两个人先后放半径为r的圆盘,圆盘不能相叠,但边缘可以相交. 若有人放盘后没有多余的位置放下一个盘,则此人胜利. 若第一个人有必胜方案,则输出First,若第二个人有必胜方案,则输出Second.

Data Limit:1 ≤ a, b, r ≤ 100 Time Limit: 2s

Solution

不要想太多,可以O(1)出解. 开局若可以放盘子,则放正中间.由于神奇的中心对称,总还剩下4n(n为自然数)个可放盘子的位置 这时第一个人只要放和第二个人对称的地方就能胜利. 所以,只要一开始有地方放,第一个人就赢了,否则第二个人才会赢.

Code

#include<cstdio>
int n,i,j,m,r;
int main()
{
    scanf("%d%d%d",&n,&m,&r);
    r=r*2;
    n=n/r;m=m/r;
    if (n==0||m==0)puts("Second");else puts("First");
    return 0;
}

B

Problem description

给出两个多项式, P(x) = a0·x^n + a1·x^n - 1 + ... + an - 1·x + an Q(x) = b0·x^m + b1·x^m - 1 + ... + bm - 1·x + bm. 求出P(x)/Q(x)的极限值.

Data Limit:0 ≤ n, m ≤ 100 - 100 ≤ ai ≤ 100, a0 ≠ 0 - 100 ≤ bi ≤ 100, b0 ≠ 0  Time Limit: 2s

Solution

分类讨论 1.若m>n,则当x无限大时,P(x)/Q(x)为0. 2.若m<n,则当x无限大时,P(x)/Q(x)为正或负无限大,其正负与a0和b0有关. 3.若m=n,则当x无限大时,P(x)/Q(x)为a0/b0,化简后输出即可.

Code

#include<cstdio>
int n,i,j,m,r,t;
int a[10000],b[10000];
bool bo=false;
int gcd(int a,int b)
{
    if (a%b==0)return b;
    return gcd(b,a%b);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (i=0;i<=n;i++)scanf("%d",&a[i]);
    for (i=0;i<=m;i++)scanf("%d",&b[i]);
    if (a[0]<0)
    {
        a[0]=-a[0];
        bo=true;
    }
    if (b[0]<0)
    {
        b[0]=-b[0];
        bo=!bo;
    }
    if (n>m)
    {
        if (bo)puts("-Infinity");else puts("Infinity");
        return 0;
    }
    if (n<m)
    {
        puts("0/1");
        return 0;
    }
    
    if (a[0]>b[0])t=gcd(a[0],b[0]);else t=gcd(b[0],a[0]);
    if (bo)printf("%s","-");
    printf("%d/%d",a[0]/t,b[0]/t);
    return 0;
}

C

Problem description

求一个字符串s的最大字典序子序列.

Data Limit:length(s) <= 1e5  Time Limit: 1s

Solution

乱搞即可,先取光所有字典序最大的字符,然后取剩下的所有字典序最大的字符直至取光.

Code

var
  s:ansistring;
  n,i,j:longint;
  hz:array[1..200000,'a'..'z']of longint;
  top:char;
begin
  readln(s);
  for i:=length(s) downto 1 do
  begin
    hz[i]:=hz[i+1];
    inc(hz[i,s[i]]);
  end;
  top:='z';
  for i:=1 to length(s) do
  begin
    while (hz[i,top]=0) do dec(top);
    if top=s[i] then write(s[i]);
  end;
end.

D

Problem description

有一个迷宫由路和墙组成,且次迷宫无限,但每个n*m的矩阵是相同的. 若可以从给定的一个起点走到无限远处,则输出Yes,否则输出No

Data Limit:1 ≤ n, m ≤ 1500  Time Limit: 1s

Solution

dfs,如果能从一个点,走到另一个矩阵的同一个点,则输出Yes,否则输出No

Code

#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
  
using namespace std;  
  
const int maxn=2000;  
char mp[maxn][maxn];  
int n,m;  
  
typedef pair<int,int> pII;  
const int dir_x[4]={1,-1,0,0};  
const int dir_y[4]={0,0,1,-1};  
  
pII last[maxn][maxn];  
bool ret=false;  
  
void dfs(int x,int y)  
{  
    int mx=x%n,my=y%m;  
    if(mp[mx][my]=='#'||ret||last[mx][my]==pII(x,y)) return;  
    if(last[mx][my]!=pII(0,0))  
    {  
        ret=true; return ;  
    }  
    last[mx][my]=pII(x,y);  
    for(int i=0;i<4;i++)  
    {  
        dfs(x+dir_x[i],y+dir_y[i]);  
    }  
}  
  
int main()  
{  
    scanf("%d%d",&n,&m);  
    for(int i=0;i<n;i++)  
        scanf("%s",mp[i]);  
    int sx,sy;  
    for(int i=0;i<n;i++)  
    {  
        for(int j=0;j<m;j++)  
        {  
            if(mp[i][j]=='S')  
                sx=i,sy=j;  
        }  
    }  
    dfs(sx+n*m,sy+n*m);  
    if(ret) puts("Yes");  
    else puts("No");  
    return 0;  
}  

E

Problem description

给出一个n个点的树与在平面上的n个点,使这些点一一对应,并且节点之间的连线不相交.

Data Limit:1 ≤ n ≤ 1500  Time Limit: 1s

Solution

由于没有3点共线的情况,所以解总是存在的。 我们考虑以当前平面左下角的点p作为树根,对平面上的点以p做基准进行极角排序,则所有点与p点的连线都不会有除了p以外的交点。 现在我们已经会填树根处的点了,对于树根的每个子节点,我们都可以递归的处理以其为根的子树, 假设该子树包含x个节点,我们考虑以一根从p出发,长度不限的射线,从p的正下方开始按逆时针扫过去, 直到扫过的平面包含x个节点即可停止。此时扫过的平面即为该子树应当处理的平面。 每次处理需要先找到左下角的点,然后对当前平面的所有点进行排序,共需要处理n次,所以复杂度O(n^2*logn)。

Code

#include <cstdio>
#include <algorithm>
#include <vector>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
typedef long long ll;
using namespace std;
const int N = 2005;
const int M = 24005;
pair<ll,ll>ori;
vector<ll>edg[N];
ll n,m,k;
ll sz[N],ans[N];
struct man{
    ll x,y,id;
    bool operator < (const man & b) const {
        return (x-ori.first)*(b.y-ori.second) - (y-ori.second)*(b.x-ori.first) > 0;
    }
}p[N];
void dfs1(ll u,ll fa){
    sz[u]=1;
    for(int i=0;i<edg[u].size();i++){
        ll v=edg[u][i];
        if(v==fa)continue;
        dfs1(v,u);
        sz[u]+=sz[v];
    }
}
void dfs2(ll u,ll fa,ll s,ll e){
    int pos;
    ll x,y;
    x=y=1e10;
    for(int i=s;i<=e;i++){
        if(p[i].x<x||((p[i].x==x)&&p[i].y<y)){
            x=p[i].x;y=p[i].y;pos=i;
        }
    }
    ori.first=x;ori.second=y;
    swap(p[s],p[pos]);
    sort(p+s+1,p+e+1);
    ans[p[s].id]=u;
    int cnt=0;
    for(int i=0;i<edg[u].size();i++){
        ll v=edg[u][i];
        if(v==fa)continue;
        dfs2(v,u,s+1+cnt,s+1+cnt+sz[v]-1);
        cnt+=sz[v];
    }
}
int main()
{
    ll T,u,v;
    scanf("%lld",&n);
    for(int i=1;i<n;i++){
        scanf("%lld%lld",&u,&v);
        edg[u].pb(v);edg[v].pb(u);
    }
    for(int i=0;i<n;i++){
        scanf("%lld%lld",&p[i].x,&p[i].y);
        p[i].id=i;
    }
    dfs1(1,0);
    dfs2(1,0,0,n-1);
    for(int i=0;i<n;i++)printf("%lld ",ans[i]);printf("
");
    return 0;
}
原文地址:https://www.cnblogs.com/Orange-User/p/7470561.html