Codeforces_807

A. 严格按照题目给的两个条件来。

#include<bits/stdc++.h>
using namespace std;

int n,a[1005],b[1005];

int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for(int i = 1;i <= n;i++)   cin >> a[i] >> b[i];
    int flag1 = 0,flag2 = 0;
    for(int i = 1;i <= n;i++)
    {
        if(a[i] != b[i])    flag1 = 1;
    }
    for(int i = 1;i < n;i++)
    {
        if(a[i] < a[i+1])   flag2 = 1;
    }
    if(flag1)   cout << "rated" <<endl;
    else if(flag2)  cout << "unrated" << endl;
    else    cout << "maybe" << endl;
    return 0;
}
View Code

B.可能的值为xx = x+50k(xx >= y),从小到大枚举每一个可能的值,计算cnt就可以了。

#include<bits/stdc++.h>
using namespace std;

int x,y,p,a[30];

int main()
{
    ios::sync_with_stdio(false);
    cin >> p >> x >> y;
    int xx = x;
    while(x >= y)
    {
        int t = x/50%475;
        for(int i = 1;i <= 25;i++)
        {
            t = (t*96+42)%475;
            a[i] = t+26;
            if(a[i] == p)
            {
                cout << 0 << endl;
                return 0;
            }
        }
        x -= 50;
    }
    x = xx;
    int cnt = 0,now = 1;
    while(1)
    {
        int t = x/50%475;
        for(int i = 1;i <= 25;i++)
        {
            t = (t*96+42)%475;
            a[i] = t+26;
            if(a[i] == p)
            {
                cout << cnt << endl;
                return 0;
            }
        }
        x += 50;
        now++;
        if(now == 2)
        {
            now = 0;
            cnt++;
        }
    }
    return 0;
}
View Code

C.先判断0和-1的情况,然后按大小分类。

若x/y < p/q,我们要把x/y变得尽量大,并且最后的值是p/q,可以变成(np-(y-x))/nq,计算n向上取整,然后结果为nq-y。

若x/y > p/q,我们要把x/y变得尽量小,即只加分母,不加分子,最后变成x/nq == np/nq,计算n向上取整,结果同上。

#include<bits/stdc++.h>
using namespace std;

long long x,y,xx,yy;

int main()
{
    ios::sync_with_stdio(false);
    int T;
    cin >> T;
    while(T--)
    {
        cin >> x >> y >> xx >> yy;
        if(x*yy == y*xx)
        {
            cout << 0 << endl;
            continue;
        }
        if(x != 0 && xx == 0 || xx >= yy)
        {
            cout << -1 << endl;
            continue;
        }
        if(x*yy < xx*y)
        {
            long long t = y-x;
            long long ans = t/(yy-xx);
            if(ans*yy-t < ans*xx)   ans++;
            cout << ans*yy-y << endl;
        }
        else
        {
            long long ans = x/xx;
            if(ans*xx < x)  ans++;
            cout << ans*yy-y << endl;
        }
    }
    return 0;
}
View Code

还可以二分n值来写。


D.暴力枚举到100000就可以了。

#include<bits/stdc++.h>
using namespace std;

int n,a[100005][10],b[100005] = {0},c[100005];

int calc(int x,int y,int z)
{
    int t = 250-x;
    if(x == -1) return 0;
    if(2*y > z) return 2*t;
    if(4*y > z) return 4*t;
    if(8*y > z) return 6*t;
    if(16*y > z)    return 8*t;
    if(32*y > z)    return 10*t;
    return 12*t;
}

bool ok(int x)
{
    int sum1 = 0,sum2 = 0;
    for(int i = 1;i <= 5;i++)   c[i] = b[i];
    for(int i = 1;i <= 5;i++)
    {
        if(a[2][i] != -1 && a[1][i] > a[2][i]) c[i] += x;
    }
    for(int i = 1;i <= 5;i++)
    {
        sum1 += calc(a[1][i],c[i],n+x);
        sum2 += calc(a[2][i],c[i],n+x);
    }
    return sum1 > sum2;
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for(int i = 1;i <= n;i++)
    {
        for(int j = 1;j <= 5;j++)
        {
            cin >> a[i][j];
            if(a[i][j] >= 0)    b[j]++;
        }
    }
    for(int i = 0;i <= 1000000;i++)
    {
        if(ok(i))
        {
            cout << i << endl;
            return 0;
        }
    }
    cout << -1 << endl;
    return 0;
}
View Code

E.分别对2的倍数,与2倍数间隔间的数计数,结果个数最多为1的个数,对每个个数,我们判断其是否可行。

我们贪心当前2的倍数之后一个的2的倍数,使剩下来的2的倍数的数量和非2倍数数量和尽可能少,因为剩下的个数为最小的划分的数的个数。

#include<bits/stdc++.h>
using namespace std;

int n,now = 0,num[65] = {0},two[65] = {0},ans[100005];

bool ok(int x)
{
    int t = two[0]-x;
    for(int i = 1;i <= now;i++)
    {
        if(x >= two[i])
        {
            t -= min(x-two[i],t);
            x = two[i];
        }
        else    t += two[i]-x;
        t += num[i];
    }
    if(t <= x)  return 1;
    return 0;
}

int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    long long t = 1;
    for(int i = 1;i <= n;i++)
    {
        long long x;
        cin >> x;
        if(x == t)  two[now]++;
        else if(x < t)  num[now-1]++;
        else
        {
            while(t < x)
            {
                t *= 2;
                now++;
            }
            if(x == t)  two[now]++;
            else    num[now-1]++;
        }
    }
    int cnt = 0;
    for(int i = 1;i <= two[0];i++)
    {
        if(ok(i))   ans[++cnt] = i;
    }
    if(cnt == 0)    cout << -1 << endl;
    else
    {
        for(int i = 1;i <= cnt;i++) cout << ans[i] << " ";
        cout << endl;
    }
    return 0;
}
View Code

F.首先一种特殊情况,我们选择权值最小(w0)的一条边,设其两点为A,B,不难理解,A,B两点的总p值均为(n-1)*w0。

然后,对于其他的点,取点a,每个点连接着(n-1)条边,对于每条边,权值为w1,设它连的点为a,b,那么,我们可以把除a,b外的所有点先连成最小,即所有边最终跑向A或B,即(n-3)*w0,然后连接A到b或者B到b,再b到a,这里最后两条路径的权值分为两种情况:①若前一点->b 大于 b->a,则总p值为(n-3)*w0+2*w1

②若前一点->b 小于 b->a,则总p值为(n-3)*w0+w前一点->b+w1

这样的情况下,我们在(n-1)*2种情况里取的最小p值为最优解。

第一种情况比较好求解,第二种情况我们可以从到b点的最优转换而来,把原来的a去掉,在最后加上b->a,即-minn+w1

这样我们就对求解顺序有一定的要求,按边权值从小到大排序,每次更新边的两个点,是符合要求的。

#include<bits/stdc++.h>
using namespace std;

int n;
long long ans[2005];
struct xx
{
    int u,v,w;
    xx(int a,int b,int c):u(a),v(b),w(c){};
    friend bool operator <(xx a,xx b)
    {
        return a.w < b.w;
    }
};

vector<xx> v;

int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for(int i = 1;i <= n;i++)   ans[i] = 1e18;
    for(int i = 1;i <= n;i++)
    {
        for(int j = i+1;j <= n;j++)
        {
            int x;
            cin >> x;
            v.push_back(xx(i,j,x));
        }
    }
    sort(v.begin(),v.end());
    long long minn = v[0].w;
    for(int i = 0;i < v.size();i++)
    {
        int x = v[i].u,y = v[i].v,w = v[i].w;
        long long t = (long long)w*2+minn*(n-3);
        ans[x] = min(ans[x],min(ans[y]-minn+w,t));
        ans[y] = min(ans[y],min(ans[x]-minn+w,t));
    }
    for(int i = 1;i <= n;i++)   cout << ans[i] << endl;
    return 0;
}
View Code

 

posted @ 2017-05-08 15:57  zzzzzzzzhu  阅读(200)  评论(0编辑  收藏  举报