1. 程式人生 > >2017年多校聯合訓練 第六場(福州大學)

2017年多校聯合訓練 第六場(福州大學)

官方題解
1002 Mindis
hdoj6097題目連結
幾何方法:
將點P關於圓O的反演點記作P',由定義得OP*OP'=r2,則△ODP~△ODP',相似比為OP:R,點Q同理
當反演點的連線與圓有交點時,min(DP+DQ)轉化為min(DP'+DQ')*相似比
否則D即為△OPQ中從點O出發的角平分線(等腰三角形三線合一)與圓的交點,計算DP+DQ
程式碼種用複數形式記錄點,abs( )返回模值,norm( )返回模的平方

#include<bits/stdc++.h>
using namespace std;
typedef complex<double> V;
int
main() { int t; scanf("%d",&t); while(t--){ double r,x,y,s; scanf("%lf",&r); scanf("%lf%lf",&x,&y); V p=V(x,y); scanf("%lf%lf",&x,&y); V q=V(x,y); if(p==q) s=2*(r-abs(p)); //特殊情況:兩點重合 else{ V pp=p*r*r/norm(p); V qq=q*r*r/norm(q); if
(norm(pp)-norm(pp-qq)/4<=r*r) s=abs(pp-qq)*abs(p)/r; //△OP'Q'的高小於等於R,則反演點連線與圓O有交點 else{ V mid=p+q; if(p==-q) mid=V(-p.imag(),p.real()); mid=mid/abs(mid)*r; //mid表示角平分線與圓的交點 s=2*abs(mid-p); } } printf("%.7f\n"
,s); } }

1003 Inversion
hdoj6098題目連結
優雅的暴力做法:
排序後找到下標不能整除當前下標的最大值

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int v,p;
    bool operator < (const node& x) const { return v>x.v; }
}a[100005];
int main()
{
    int t,n,i,j;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(i=1;i<=n;i++) scanf("%d",&a[i].v),a[i].p=i;
        sort(a+1,a+1+n);
        for(i=2;i<=n;i++){
            for(j=1;j<=n&&a[j].p%i==0;j++);
            printf("%d%c",a[j].v,i==n?'\n':' ');
        }
    }
}

1008 Kirinriki
hdoj6103題目連結
迴文串,列舉對稱軸,雙指標維護

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t,m,len,ans,cnt,sum,l,x,r,y,i;
    char s[5005];
    scanf("%d",&t);
    while(t--){
        scanf("%d%s",&m,s+1);
        len=strlen(s+1);
        ans=0;
        for(i=2;i<len;i++){ //以下標為i的字元為對稱軸
            l=x=i-1,r=y=i+1;
            cnt=sum=0;
            while(l&&r<=len){
                sum+=abs(s[l]-s[r]),cnt++;
                if(sum<=m) ans=max(ans,cnt);
                else{
                    while(sum>m){
                        sum-=abs(s[x]-s[y]);
                        x--,y++;
                        cnt--;
                    }
                }
                l--,r++;
            }
        }
        for(i=1;i<len;i++){ //以下標為i的字元右側間隙為對稱軸
            l=x=i,r=y=i+1;
            cnt=sum=0;
            while(l&&r<=len){
                sum+=abs(s[l]-s[r]),cnt++;
                if(sum<=m) ans=max(ans,cnt);
                else{
                    while(sum>m){
                        sum-=abs(s[x]-s[y]);
                        x--,y++;
                        cnt--;
                    }
                }
                l--,r++;
            }
        }
        printf("%d\n",ans);
    }
}

1010 Gameia
hdoj6105題目連結
//比賽最後1h開了這題,菜雞QYQ和Dsaitou玩了好幾把,一直沒啥頭緒。只見lza11111一眼看穿規律,1A,撒花
如果Bob能把這棵樹分成若干兩個一組的點對,那麼Bob取得勝利,否則Alice獲勝:
程式碼中首先特判了結點個數為奇,Bob超能力使用次數不夠的情況,都是Alice獲勝。
然後暴力列舉葉子結點,若存在有多個兒子節點時葉子節點的情況,那麼Alice獲勝。

#include<bits/stdc++.h>
using namespace std;
#define N 505
int main()
{
    int t,n,k,d[N],f[N],i,j,fg;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        memset(d,0,sizeof(d));
        for(i=2;i<=n;i++) scanf("%d",&f[i]),d[i]++,d[f[i]]++;
        if(n&1||k<n/2-1) { puts("Alice");continue; }
        for(fg=0,i=2;i<=n;i++)if(d[i]==1){
            for(j=i+1;j<=n;j++)if(f[i]==f[j]&&d[j]==1) { fg=1;break; }
        }
        puts(fg?"Alice":"Bob");
    }
}

1011 Classes
hdoj6106題目連結
簽到快樂

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t,n,mx,a,b,c,ab,bc,ac,abc;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        mx=0;
        while(n--){
            scanf("%d%d%d%d%d%d%d",&a,&b,&c,&ab,&bc,&ac,&abc);
            ab-=abc,bc-=abc,ac-=abc;
            if(ab<0||bc<0||ac<0) continue;
            a-=ab+ac+abc,b-=bc+ab+abc,c-=bc+ac+abc;
            if(a<0||b<0||c<0) continue;
            mx=max(mx,a+b+c+ab+bc+ac+abc);
        }
        printf("%d\n",mx);
    }
}