Codeforces Global Round 6

A

题意:

给你一个只包含数字的字符串,你可以将字符串随机排列,问最后组成的数字能否被60整除

分析:

我们先考虑能被6整除的数的特点:

①各个位数和 % 3 == 0

②末尾数必须为 0 2 4 6 8中的一个

再考虑能被10整除的数的特点:

末尾数必须为0

因为60中6在十位部分 ,10在个位部分,所以最后组成的数除了各个位数和 % 3 == 0 外十位部分必须为0 、2 、4、6、8 中的一个, 个位数必须为0。

int main()
{
    ios;
    int n ;
    cin >> n;
    while(n --) 
    {
        ha.clear();
        string s;
        cin >> s;
        int len = s.size() - 1;
        int tot = 0;
        rep(j , 0 , len)
        {
            ha[s[j] - '0'] ++;
            tot += s[j] - '0';
        }
        if(ha[0] && (ha[2] || ha[4] || ha[6] || ha[8] || (ha[0] - 1)) && tot % 3 == 0)
        cout << "red" << '
';
        else cout << "cyan" << '
';
 
    }
    return 0;
}

  B

有无限个骰子,你可以从中选出任意个来拼搭,问“没有被挡住的点数的和”能否组成某个数X(就是一个一个叠加上去)

你会发现除了最上面一个,其他的筛子都是对立面被挡了,也就是每个筛子贡献14,所以只需x%=14,在判断x在不在【1,6】范围内

C

要求构造一个 r 行 c 列的矩阵, 并且矩阵的每一行的gcd和每一列的gcd的都只出现过一次,且每行的gcd都要求最小

一段连续自然数的gcd肯定是1,所以我门把第一列连续1,第二列为第一列翻倍,那么这一列就是2,第三列就是3....

然后每行gcd就是该行第一个元素

要构成这个,你的第一列第一个元素应该大于列数,例如 3 2

那么 

3 6

4 8

5 10

这样第一列是1,第二列是2,第一行是3 第二行是4第三行是5;

int main()
{
    ios;
    ll r , c;
    cin >> r >> c;
    if(r == 1  && c == 1)
    return cout << 0 << '
' , 0; 
    if(r == 1)
    {
        int tot = 2;
        rep(i , 1 , c)
        cout << tot ++ << ' ';
        return 0;
    }
    if(c == 1)
    {
        int tot = 2;
        rep(i , 1 , r)
        cout << tot ++ << "
";
        return 0;
    }
    
    rep(i , 1 , r)
    {
        rep(j , 1 , c)
        {
            a[i][j] = i * (j + r);
        }
    }
    rep(i , 1 , r)
    {
        rep(j , 1 , c)
        cout << a[i][j] << " ";
        cout << '
';
    }
    
        return 0;
}

  D

题意:

给你几个债务关系,如A欠B五元, B欠C五元,此时总的债务为 5 + 5 = 10 。

我们可以把关系转换为A欠C五元,那这样总的债务为 5 

问不限转换次数 , 怎么把总债务化为最小。

分析:

当把总债务化为最小时 , 每个人的债务关系也将是最简的(以上述例子阐述,对B , 它欠C五元,这时候它的支出为5,但是A欠它五元,所以它的收入为5,所以它最后对总债务的关系为abs(5 - 5)= 0)

对于A、C也是一样的,所以最后A的最简形式为A支出5元,B的最简形式为0,C的最简形式为收入5元。按照这样,我们只要将A指向C即可

(因为总的收入和总的支出一定是相同的且题目也说债务关系数量最小,所以即使某个人 D 收入的金额大于另一个人 E 支出的金额,也可以先将E连向D,然后D的收入金额减去E的支出金额)

我们用 in 容器来存最简形式为收入的人的编号, ou容器来存最简形式为支出的人的编号,再用指针one指向in里的元素,two指向ou里的元素,他们的债务可以表示为min(a[one] , a[two]) , 将关系存于ans容器里。

当one == in.size() || two == ou.size() 即已经没有支出的人或已经没有收入的人了,则债务关系可以结束储存(题目要求最后输出债务关系)         

const int N = 3e5 + 10;
ll a[N];
vector<ll>in , ou;
vector<pair<pair<ll , ll>, ll> > ans;
int main()
{
    ios;
    ll n , m ;
    cin >> n >> m;
    rep(i , 1 , m)
    {
        ll x , y , z;
        cin >> x >> y >> z;
        a[x] += z;
        a[y] -= z;
    }
    rep(i , 1 , n)
    {
        if(a[i] > 0)
        in.pb(i);
        else if(a[i] < 0)
        ou.pb(i);
    }
    ll one = 0 , two = 0;
    while(true)
    {
        if(one == in.size() || two == ou.size())
            break;
        ll ha = min(a[in[one]] , -a[ou[two]]);
        ans.pb(make_pair(make_pair(in[one] , ou[two]) , ha));
        a[in[one]] -= ha;
        a[ou[two]] += ha;
        if(!a[in[one]]) one ++;
        if(!a[ou[two]]) two ++;
    }
    ll len = ans.size();
    cout << len << '
';
    rep(i , 0 , len - 1)
    cout << ans[i].fi.fi << " " << ans[i].fi.se << " " << ans[i].se << "
";
    return 0;
}

  

原文地址:https://www.cnblogs.com/hgangang/p/12219390.html