2016 Multi-University Training Contest 2

hdu5734 Acperience

題意:說了一大堆,求求和(wi - x * bi),使和最小,wi已知,x非負數,bi取-1或1

題解:列出二次方程,初中知識各種變就行

          最後答案是(n * 求和(wi^2) -  (求和(wi*bi))^2)

int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        LL x,sum1=0,sum2=0;
        for(int i=0;i<n;i++){
            scanf("%I64d",&x);
            sum1+=(LL)x*x;
            sum2+=abs(x);
        }
        LL ans1=(LL)n*sum1-sum2*sum2;
        LL ans2=(LL)n;
        //cout<<ans1<<' '<<ans2<<endl;
        printf("%I64d/%I64d\n",ans1/__gcd(ans1,ans2),ans2/__gcd(ans1,ans2));
    }
    return 0;
}

hdu5738 Eureka

題意:問有多少個點集合,點集合裏面有三點共線

題解:每次選擇相對最下左的點,考慮這個點上右方的點,保存斜率就好

           需要注意的是,可能有點的座標相同

LL exp(LL a, LL b, LL c){
    LL ans = 1, temp;
    a = a % c;
    temp = a;
    while(b){
        if(b&1){
            ans = ans * temp % c;
        }
        temp = temp * temp % c;
        b /= 2;
    }
    return ans;
}

struct point {
    LL x, y;
    bool operator<(const point&x)const{
        if(this->x==x.x)
            return this->y<x.y;
        else
            return this->x<x.x;
    }
}p[1010];

bool cmp (point a, point b){
    if(a.x == b.x)
        return a.y < b.y;
    else
        return a.x < b.x;
}

map <point, LL> m1;
map <point, LL> m2;

int main(){
    int t,n;
    cin>>t;
    while(t--){
        cin>>n;
        m1.clear();
        m2.clear();
        for(int i=0;i<n;i++){
            cin>>p[i].x>>p[i].y;
        }
        sort(p,p+n,cmp);
        LL ans = 0;
        for(int i=0;i<n;i++){
            if(m2[p[i]])
                continue;
            m1.clear();
            for(int j=i+1;j<n;j++){
                LL x = p[j].x - p[i].x;
                LL y = p[j].y - p[i].y;
                if(x < 0){
                    x = -x;
                    y = -y;
                }
                LL temp = __gcd(x, abs(y));
                if(x!=0 && y!=0){
                    if(x == 0)
                        y = 1;
                    if(y == 0)
                        x = 1;
                }
                if(temp){
                    x /= temp;
                    y /= temp;
                }
                point tt;
                tt.x = x;
                tt.y = y;
                m1[tt]++;
            }
            LL ll;
            point pp;
            pp.x=0;pp.y=0;
            LL ll1 = m1[pp];
            for(map<point, LL>::iterator it = m1.begin();it != m1.end();it ++){
                if(it->first.x == 0 && it->first.y == 0){
                    ll = exp(2, it->second + 1, mod);
                    ll = ll - it->second - 2;
                    ans += ll;
                    ans %= mod;
                }
                else {
                    ll = exp(2, it->second, mod);
                    ll--;
                    ans += (ll*(exp(2, ll1+1, mod)-1));
                    ans %= mod;
                }
            }
            m2[p[i]] = 1;
        }
        ans %= mod;
        cout<<ans<<endl;
    }
    return 0;
}

hdu5742 It's All In The Mind

題意:數列,有些數未知,遞減,求最大(a[1] + a[2]) /  總和

題解:貪心,使a[1] + a[2]儘可能大,總和儘可能小

int main(){
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        int x,y;
        if(m==0 || n==2){
            printf("1/1\n");
            continue;
        }
        memset(a,-1,sizeof(a));
        for(int i=0;i<m;i++){
            cin>>x>>y;
            a[x]=y;
        }
        if(a[1]==-1 && a[2]==-1){
            a[1]=100;
            a[2]=100;
        }
        else if(a[1]==-1){
            a[1]=100;
        }
        else if(a[2]==-1){
            a[2]=a[1];
        }
        int temp=0;
        for(int i=n;i>=3;i--){
            if(a[i]==-1){
                a[i]=temp;
            }
            else {
                temp=a[i];
            }
        }
        int ans1=a[1]+a[2],ans2=0;
        for(int i=1;i<=n;i++){
            ans2+=a[i];
        }
        printf("%d/%d\n",ans1/__gcd(ans1,ans2),ans2/__gcd(ans1,ans2));
    }
    return 0;
}

hdu5744 Keep On Movin

題意:n個字符,每個字符有ai個,可以組成x個迴文串,問所有迴文串中最短的最大值是多少

題解:最大化最小值,第一想法,二分

           仔細想想,其實不用二分,如果一個字符有奇數個,那麼必須要在某個串的中間放一個,如果是偶數,隨便添加進去就可以,找到有多少奇數個,剩下的往兩邊分配就好

int a[100010];

int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int sum=0,sum1=0;
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            if(a[i]&1){
                sum++;
                a[i]--;
            }
            sum1+=a[i];
        }
        if(sum<=0){
            cout<<sum1<<endl;
        }
        else {
            cout<<sum1/2/sum*2+1<<endl;
        }
    }
    return 0;
}


發佈了37 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章