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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章