• 2011 Multi-University Training Contest 1


    A.A + B problem(待填坑)

    B.Cat VS Dog(二分图匹配)

    喜欢cat和喜欢dog的人构成了二分图,如果两个人有冲突则连一条边,则问题转化为二分图最大点独立集问题。ans=n-最大匹配。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=505;
    //Code begin...
    
    struct Child{string like, dis;}cat[N], dog[N];
    int G[N][N], link[N], used[N], cat_num, dog_num;
    
    int dfs(int k)
    {
        FO(i,0,dog_num) if(!used[i] && G[k][i])  {
            used[i]=1;
            if(link[i]==-1 || dfs(link[i])) {link[i]=k; return 1;}
        }
        return 0;
    }
    int maxMatch()
    {
        int cnt=0;
        FO(i,0,cat_num) {
            mem(used,0);
            if(dfs(i))  ++cnt;
        }
        return cnt;
    }
    int main()
    {
        int n, m, p;
        string a, b;
        while(cin>>n>>m>>p)  {
            mem(G,0); mem(link,-1);
            cat_num=dog_num=0;
            while(p--) {
                cin>>a>>b;
                if(a[0] == 'C') cat[cat_num].like=a, cat[cat_num].dis=b, cat_num++;
                else  dog[dog_num].like=a, dog[dog_num].dis=b, dog_num++;
            }
            FO(i,0,cat_num) FO(j,0,dog_num) if(cat[i].like==dog[j].dis || cat[i].dis==dog[j].like)  G[i][j]=1;
            cout<<cat_num+dog_num-maxMatch()<<endl;
        }
        return 0;
    }
    View Code

    C.Checkers(二分+LCA+辗转相除法)

    考虑点对(a,b,c)可以转换的点对。容易发现这其实是一个无限二叉树。

    如果左边的棋子或者右边的棋子往中间跳,就对应着父亲边往上的过程。中间的棋子往左跳,对应着左孩子边。中间的往右跳,对应着右孩子边。

    那么我们判断解的存在性就相当于找到他们是不是同一个根。判断最小的解就相当于在树上找到LCA。

    可以通过辗转相除法来优化向上爬的操作。由于不能倍增找LCA,我们二分向上爬的深度验证即可。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 100000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=505;
    //Code begin...
    
    LL a[3], b[3], root[2], dep[2], dis[2], temp1[3], temp2[3];
    
    void get_root(LL x)
    {
        root[x]=(x?b[1]:a[1]); dep[x]=0;
        LL val1, val2, t;
        if (x) val1=b[1]-b[0], val2=b[2]-b[1];
        else val1=a[1]-a[0], val2=a[2]-a[1];
        while (val1!=val2) {
            if (val1<val2) {
                if (val2%val1) t=val2/val1;
                else t=val2/val1-1;
                root[x]+=t*val1; dep[x]+=t; val2-=t*val1;
            }
            else {
                if (val1%val2) t=val1/val2;
                else t=val1/val2-1;
                root[x]-=t*val2; dep[x]+=t; val1-=t*val2;
            }
        }
        dis[x]=val1;
    }
    void go_up(LL (&a)[3], LL dep)
    {
        while (dep) {
            LL val1=a[1]-a[0], val2=a[2]-a[1], t;
            if (val1>val2) {
                if (val1%val2) t=val1/val2;
                else t=val1/val2-1;
                if (dep>=t) a[1]-=t*val2, a[2]-=t*val2, dep-=t;
                else a[1]-=dep*val2, a[2]-=dep*val2, dep=0;
            }
            else {
                if (val2%val1) t=val2/val1;
                else t=val2/val1-1;
                if (dep>=t) a[1]+=t*val1, a[0]+=t*val1, dep-=t;
                else a[1]+=dep*val1, a[0]+=dep*val1, dep=0;
            }
        }
    }
    int main ()
    {
        while (~scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a[0],&a[1],&a[2],&b[0],&b[1],&b[2])) {
            sort(a,a+3); sort(b,b+3);
            get_root(0); get_root(1);
            if (root[0]!=root[1] || dis[0]!=dis[1]) {puts("NO"); continue;}
            LL ans=0;
            if (dep[0]>dep[1]) {
                LL t=dep[0]-dep[1]; dep[0]=dep[1];
                go_up(a,t);
                ans+=t;
            }
            else if (dep[0]<dep[1]) {
                LL t=dep[1]-dep[0]; dep[1]=dep[0];
                go_up(b,t);
                ans+=t;
            }
            if (a[0]==b[0]&&a[1]==b[1]&&a[2]==b[2]) {printf("YES
    %I64d
    ",ans); continue;}
            LL l=0, r=dep[0]+1, mid;
            while (l<r) {
                mid=(l+r)>>1;
                temp1[0]=a[0]; temp1[1]=a[1]; temp1[2]=a[2];
                temp2[0]=b[0]; temp2[1]=b[1]; temp2[2]=b[2];
                go_up(temp1,mid); go_up(temp2,mid);
                if (temp1[0]==temp2[0]&&temp1[1]==temp2[1]&&temp1[2]==temp2[2]) r=mid;
                else l=mid+1;
            }
            printf("YES
    %I64d
    ",ans+2*r);
        }
        return 0;
    }
    View Code

    D.DICS(DP)

    这是字符串编辑距离的拓展,多了一个改变后缀操作。dp数组多开一维记录改变的后缀类型。直接记搜即可。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 100000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=505;
    //Code begin...
    
    int dp[N][N][55], len1, len2;
    char s1[N], s2[N];
    
    int dfs(int x, int y, int z)
    {
        if (~dp[x][y][z]) return dp[x][y][z];
        if (x==len1&&y==len2) return 0;
        if (x==len1) return len2-y;
        if (y==len2) return len1-x;
        int ans=min(dfs(x,y+1,z)+1,dfs(x+1,y,z)+1);
        if (z==0) ans=min(ans,dfs(x+1,y+1,z)+(s1[x]!=s2[y]));
        else ans=min(ans,dfs(x+1,y+1,z)+(z!=s2[y]));
        if ((z==0&&s1[x]!=s2[y]) || (z&&z!=s2[y])) ans=min(ans,dfs(x+1,y+1,s2[y])+1);
        return dp[x][y][z]=ans;
    }
    int main ()
    {
        while (1) {
            scanf("%s",s1);
            if (s1[0]=='#') break;
            scanf("%s",s2);
            len1=strlen(s1); len2=strlen(s2);
            FO(i,0,len1) {
                if (s1[i]<='z'&&s1[i]>='a') s1[i]=s1[i]-'a'+1;
                else s1[i]=s1[i]-'A'+27;
            }
            FO(i,0,len2) {
                if (s2[i]<='z'&&s2[i]>='a') s2[i]=s2[i]-'a'+1;
                else s2[i]=s2[i]-'A'+27;
            }
            mem(dp,-1);
            printf("%d
    ",dfs(0,0,0));
        }
        return 0;
    }
    View Code

    E.Earth Hour(水题)

    先抽象成图,然后问题转化为求图中3个点的生成树的最短路。数据范围很小,直接从这3个点bfs一次。因为这连接3个点的生成树一定是从图中一个点出发可以直接到达的。

    枚举这个点更新答案即可。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 100000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=205;
    //Code begin...
    
    struct Edge{int p, next;}edge[N*N];
    struct Cir{int x, y, r;}cir[N];
    int head[N], cnt, fa[N], vis[N];
    
    queue<int>Q;
    int find(int x)
    {
        int s, temp;
        for (s=x; fa[s]>=0; s=fa[s]) ;
        while (s!=x) temp=fa[x], fa[x]=s, x=temp;
        return s;
    }
    void union_set(int x, int y)
    {
        int temp=fa[x]+fa[y];
        if (fa[x]>fa[y]) fa[x]=y, fa[y]=temp;
        else fa[y]=x, fa[x]=temp;
    }
    void add_edge(int u, int v){edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;}
    void init(){cnt=1; mem(head,0); mem(fa,-1);}
    int dis(int x, int y){return (cir[x].x-cir[y].x)*(cir[x].x-cir[y].x)+(cir[x].y-cir[y].y)*(cir[x].y-cir[y].y);}
    int main ()
    {
        int T, n, u, v, w;
        scanf("%d",&T);
        while (T--) {
            int ans=0;
            init();
            scanf("%d",&n);
            FOR(i,1,n) scanf("%d%d%d",&cir[i].x,&cir[i].y,&cir[i].r);
            FOR(i,1,n) FOR(j,i+1,n) if (dis(i,j)<=(cir[i].r+cir[j].r)*(cir[i].r+cir[j].r)) {
                add_edge(i,j), add_edge(j,i);
                u=find(i), v=find(j);
                if (u!=v) union_set(u,v);
            }
            u=find(1); v=find(2); w=find(3);
            if (u!=v||u!=w||v!=w) {puts("-1"); continue;}
            FOR(i,1,n) {
                mem(vis,-1); vis[i]=0;
                while (!Q.empty()) Q.pop();
                Q.push(i);
                while (!Q.empty()) {
                    int w=Q.front(); Q.pop();
                    for (int v=head[w]; v; v=edge[v].next) {
                        int u=edge[v].p;
                        if (vis[u]!=-1) continue;
                        vis[u]=vis[w]+1; Q.push(u);
                    }
                }
                if (vis[1]!=-1&&vis[2]!=-1&&vis[3]!=-1) ans=max(ans,n-1-vis[1]-vis[2]-vis[3]);
            }
            printf("%d
    ",ans);
        }
    }
    View Code

    F.YY's new problem(线段树维护字符串hash)

    问题转化为 2*a[j]=a[i]+a[k].对于每一个a[j], 只需要验证点对(a[i],a[k])是否出现在a[j]的两侧。复杂度是O(n^2).

    如果发现对于a[j],点对是连续的,比如(a[j]-1,a[j]+1),(a[j]-2,a[j]+2),(a[j]-k,a[j]+k).

    从前往后扫描数组,如果扫描到a[m],就将vis[a[m]]置1,扫描到a[j]时,只需要验证每个点对的vis值是否是相等的。这样复杂度还是O(n^2).

    实际上点对的分布在数轴上是关于点a[j]对称的,那么我们只需要检查关于vis值字符串a[j]-k...a[j]-2,a[j]-1和字符串a[j]+k...a[j]+2,a[j]+1.是否相等就行了。

    于是我们需要一个能够快速实现更新一个点的hash,查询一个区间的hash值的数据结构,hash由于具有区间合并性。我们可以用线段树来维护区间的hash值。

    复杂度是O(nlogn).

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 100000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=10005;
    //Code begin...
    
    int a[N];
    LL seg1[N<<2], seg2[N<<2], _hash[N];
    
    LL mult_mod(LL a, LL b, LL c)
    {
        a%=c; b%=c;
        LL ret=0, tmp=a;
        while (b) {
            if (b&1) {
                ret+=tmp;
                if (ret>c) ret-=c;
            }
            tmp<<=1;
            if (tmp>c) tmp-=c;
            b>>=1;
        }
        return ret;
    }
    LL pow_mod(LL a, LL n, LL mod)
    {
        LL ret=1, temp=a%mod;
        while (n) {
            if (n&1) ret=mult_mod(ret,temp,mod);
            temp=mult_mod(temp,temp,mod);
            n>>=1;
        }
        return ret;
    }
    void init(int p, int l, int r)
    {
        if (l<r) {
            int mid=(l+r)>>1;
            init(lch); init(rch);
            seg1[p]=(seg1[p<<1]*_hash[(r-l+1)>>1]+seg1[p<<1|1])%MOD;
            seg2[p]=(seg2[p<<1|1]*_hash[(r-l+2)>>1]+seg2[p<<1])%MOD;
            return ;
        }
        seg1[p]=seg2[p]=1;
    }
    void insert(int p, int l, int r, int L)
    {
        if (L>r||L<l) return ;
        if (L==l&&L==r) seg1[p]=seg2[p]=2;
        else {
            int mid=(l+r)>>1;
            insert(lch,L); insert(rch,L);
            seg1[p]=(seg1[p<<1]*_hash[(r-l+1)>>1]+seg1[p<<1|1])%MOD;
            seg2[p]=(seg2[p<<1|1]*_hash[(r-l+2)>>1]+seg2[p<<1])%MOD;
        }
    }
    LL query1(int p, int l, int r, int L, int R)
    {
        if (L>r||R<l) return 0;
        if (L<=l&&R>=r) return seg1[p]*_hash[R-r]%MOD;
        int mid=(l+r)>>1;
        return (query1(lch,L,R)+query1(rch,L,R))%MOD;
    }
    LL query2(int p, int l, int r, int L, int R)
    {
        if (L>r||R<l) return 0;
        if (L<=l&&R>=r) return seg2[p]*_hash[l-L]%MOD;
        int mid=(l+r)>>1;
        return (query2(lch,L,R)+query2(rch,L,R))%MOD;
    }
    int main ()
    {
        int n, T, flag;
        _hash[0]=1;
        FOR(i,1,10000) _hash[i]=_hash[i-1]*131%MOD;
        scanf("%d",&T);
        while (T--) {
            flag=0;
            scanf("%d",&n);
            FOR(i,1,n) scanf("%d",a+i);
            init(1,1,n);
            FOR(i,1,n) {
                if (a[i]!=1 && a[i]!=n) {
                    int t=min(n-a[i],a[i]-1);
                    //printf("%d %lld %lld
    ",i,query1(1,1,n,a[i]-t,a[i]-1),query2(1,1,n,a[i]+1,a[i]+t));
                    if (query1(1,1,n,a[i]-t,a[i]-1)!=query2(1,1,n,a[i]+1,a[i]+t)) {flag=1; break;}
                }
                insert(1,1,n,a[i]);
            }
            puts(flag?"Y":"N");
        }
        return 0;
    }
    View Code

    G.Where am I(计算几何)

    把小圆缩成点,大圆缩小,可以发现路径只会形成一个三角形,计算出这个三角形即可。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    typedef struct
    {
    double x,y;
    }TPoint;
    typedef struct
    {
    double x,y,r;
    }TCircle;
    TCircle ball,sball;
    TPoint vec,convert;
    double T;
    int flag;
    inline double squ(double x)
    {
    return x*x;
    }
    double dot(TPoint a,TPoint b,TPoint c)
    {
    return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);
    }
    int cross(TPoint a,TPoint b,TPoint c)
    {
    double ret = (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
    if(ret>eps)
    return 1;
    return -1;
    }
    void work()
    {
    convert.x = ball.x;
    convert.y = ball.y;
    sball.x -= convert.x;
    sball.y -= convert.y;
    ball.x =0;
    ball.y = 0;
    ball.r -= sball.r;
    TPoint me = {sball.x,sball.y};
    if(fabs(vec.x) < eps && fabs(vec.y) < eps)
    {/*vec is zero*/
    me.x += convert.x;
    me.y += convert.y;
    printf("%.1f %.1f
    ",me.x,me.y);
    return;
    }
    if(fabs(ball.r)<eps)
    {/*sball.r == ball.r*/
    me.x += convert.x;
    me.y += convert.y;
    printf("%.1f %.1f
    ",me.x,me.y);
    return;
    }
    if(squ(me.x+T*vec.x)+squ(me.y+T*vec.y)+eps<squ(ball.r))
    {
    me.x = me.x+T*vec.x;
    me.y = me.y+T*vec.y;
    me.x += convert.x;
    me.y += convert.y;
    printf("%.1f %.1f
    ",me.x,me.y);
    return ;
    }
    double k=vec.y/vec.x;
    double b=me.y-k*me.x;
    double x1;
    //printf("k:%f   b:%f   %f
    ",k,b,ball.r);
    if(vec.x<0)
    {
    x1=(-k*b-sqrt(squ(k*ball.r)+squ(ball.r)-squ(b)))/(squ(k)+1);
    }
    else
    {
    x1=(-k*b+sqrt(squ(k*ball.r)+squ(ball.r)-squ(b)))/(squ(k)+1.0);
    }
    /*fjjjjj*/
    double y1=k*x1+b;
    /**
    ** x1 && y1
    **/
    // printf("(x1,y1)%f  %f
    ",x1,y1);
    TPoint tmp1 = {x1,y1};
    TPoint tmp2 = {0,0};
    double u = dot(tmp1,tmp2,me);
    flag = cross(tmp1,tmp2,me);
    /**
    flag
    **/
    //printf("flag:%d
    ",flag);
    u = u/(sqrt(squ(x1-me.x)+squ(y1-me.y))*ball.r);
    double l=(u)*ball.r;
    l *= 2;
    u = acos(u);
    /**
    l
    **/
    //printf("l:%f
    ",l);
    double t1 = l/sqrt(squ(vec.x)+squ(vec.y));
    __int64 time = (T-(x1-me.x)/vec.x)/t1;
    /**
    time
    **/
    //printf("time:%I64d
    ",time);
    T = T-(x1-me.x)/vec.x-time*t1;
    /**
    lefttime
    **/
    // printf("lefttime:%f
    ",T);
    /*上面以对  很可能是角度算错了 下面的要仔细验证下!!!*/
    double u2=atan2(y1,x1);
    double u3 = (time+1)*(pi-2*u)*flag;
    u2 += time*(pi-2*u)*flag;
    double x2 = ball.r*cos(u2);
    double y2 = ball.r*sin(u2);
    //printf("%f   %f(x2,y2)
    ",x2,y2);
    TPoint vec2;
    vec2.x = vec.x*cos(u3)-vec.y*sin(u3);
    vec2.y = vec.x*sin(u3)+vec.y*cos(u3);
    me.x = x2+vec2.x*T+convert.x;
    me.y = y2+vec2.y*T+convert.y;
    printf("%.1f %.1f
    ",me.x,me.y);
    return;
    }
    int main(void)
    {
    #ifndef ONLINE_JUDGE
    freopen("G.in","r",stdin);
    freopen("G.out","w",stdout);
    #endif
    int t;
    scanf("%d",&t);
    while(t--)
    {
    scanf("%lf%lf%lf",&ball.x,&ball.y,&ball.r);
    scanf("%lf%lf%lf",&sball.x,&sball.y,&sball.r);
    scanf("%lf%lf%lf",&vec.x,&vec.y,&T);
    work();
    }
    return 0;
    }
    View Code

    H.R(N)(水题)

    打出平方表二分搜一下即可。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    //Code begin...
    
    int a[N], P;
    
    bool bin_sea(int x)
    {
        int l=1, r=P+1, mid;
        while (l<r) {
            mid=(l+r)>>1;
            if (l==mid) break;
            if (a[mid]>x) r=mid;
            else l=mid;
        }
        return a[l]==x;
    }
    int main ()
    {
        int n;
        P=(int)sqrt(1e9+0.5);
        FOR(i,1,P) a[i]=i*i;
        while (~scanf("%d",&n)) {
            if (n==0) {puts("1"); continue;}
            LL ans=0;
            if (bin_sea(n)) ans+=4;
            FOR(i,1,n) {
                if (2*i*i>n) break;
                else if (2*i*i==n) ans+=4;
                else if (bin_sea(n-i*i)) ans+=8;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    I.Equivalent Sets(强连通分量)

    易知道当且仅当一个图是强连通图时题意成立。先把题中给出的图强连通分量缩点,然后变成了一个DAG,问题转化为求DAG最少加几条边变成强连通图。

    有结论max(源,汇)。(具体还不会证)

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 100000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=20005;
    //Code begin...
    
    struct Edge{int p, next;}edge[N<<2];
    int head[N], cnt;
    int Low[N], DFN[N], Stack[N], Belong[N], num[N];
    int Index, top, scc, a[N<<2][2], chu[N], ru[N];
    bool Instack[N];
    
    void add_edge(int u, int v){edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;}
    void Tarjan(int u)
    {
        int v;
        Low[u]=DFN[u]=++Index; Stack[top++]=u; Instack[u]=true;
        for (int i=head[u]; i; i=edge[i].next) {
            v=edge[i].p;
            if (!DFN[v]) {
                Tarjan(v);
                if (Low[u]>Low[v]) Low[u]=Low[v];
            }
            else if (Instack[v]&&Low[u]>DFN[v]) Low[u]=DFN[v];
        }
        if (Low[u]==DFN[u]) {
            scc++;
            do{
                v=Stack[--top]; Instack[v]=false;
                Belong[v]=scc; num[scc]++;
            }while (v!=u);
        }
    }
    void solve(int n)
    {
        mem(DFN,0); mem(Instack,0); mem(num,0);
        Index=scc=top=0;
        FOR(i,1,n) if (!DFN[i]) Tarjan(i);
    }
    void init(){mem(head,0); mem(chu,0); mem(ru,0); cnt=1;}
    int main ()
    {
        int n, m, u, v;
        while (~scanf("%d%d",&n,&m)) {
            init();
            FOR(i,1,m) scanf("%d%d",&u,&v), add_edge(u,v), a[i][0]=u, a[i][1]=v;
            solve(n);
            if (scc==1) {puts("0"); continue;}
            FOR(i,1,m) {
                if (Belong[a[i][0]]==Belong[a[i][1]]) continue;
                ++chu[Belong[a[i][0]]]; ++ru[Belong[a[i][1]]];
            }
            int ans1=0, ans2=0;
            FOR(i,1,scc) {
                if (chu[i]==0) ans1++;
                if (ru[i]==0) ans2++;
            }
            printf("%d
    ",max(ans1,ans2));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    10年后方向
    nginx的配置文件server_name的意义 location意义
    java程序员应该知道的20个有用的库
    集群和分布式区别
    noVNC连接CentOS,以Web方式交付VNC远程连接
    centos7.2云主机安装桌面
    centos7.2 rabbitmq3.6.2源码部署
    Linux下打包压缩war和解压war包 zip和jar
    CentOS7.2下安装mongoDB3.2.8
    centos7 mysql5.7.17源码安装
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6428899.html
Copyright © 2020-2023  润新知