TopCoder SRM 657 DIV 1

250

Problem Statement

  Cat Snuke came up with some problems. He wants to construct as many problem sets as possible using those problems. Each problem set must contain exactly three problems: one for the Easy slot, one for the Medium slot, and one for the Hard slot. Each problem can only be assigned to a single slot in a single problem set. He came up with E + EM + M + MH + H problems in total. The distribution of the problems is as follows:
  • E problems can only be used in the Easy slot.
  • EM problems can be used either in the Easy slot or the Medium slot.
  • M problems can only be used in the Medium slot.
  • MH problems can be used either in the Medium slot or the Hard slot.
  • H problems can only be used in the Hard slot.
Return the maximal number of problem sets he can construct.

Definition

 
Class: ProblemSets
Method: maxSets
Parameters: long long, long long, long long, long long, long long
Returns: long long
Method signature: long long maxSets(long long E, long long EM, long long M, long long MH, long long H)
(be sure your method is public)

Limits

 
Time limit (s): 2.000
Memory limit (MB): 256
Stack limit (MB): 256

Constraints

- E, EM, M, MH, H will be between 0 and 1,000,000,000,000,000,000 (10^18), inclusive.

Examples

0)  
 
2
2
1
2
2
Returns: 3
One of EM problems should be used for the Easy slot, and the other should be used for the Medium slot. One of MH problems should be used for the Medium slot, and the other should be used for the Hard slot.
1)  
 
100
100
100
0
0
Returns: 0
Unfortunately, no problem can be used for the Hard slot.
2)  
 
657
657
657
657
657
Returns: 1095
3)  
 
1
2
3
4
5
Returns: 3
4)  
 
1000000000000000000
1000000000000000000
1000000000000000000
1000000000000000000
1000000000000000000
Returns: 1666666666666666666

 二分,不解释

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rp(i,b) for(int i=(0);i<(b);++i)
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define repd(i,a,b) for(int i=(a);i<=(b);++i)
#define mst(a,b) memset(a,b,sizeof(a))
const int MAXN = 101005;
const ll INF = ~0ull >> 1;
inline ll min(ll a, ll b, ll c)
{
    return min(min(a, b), c);
}
class ProblemSets
{
public:
    ll e, em, m, mh, h, md;
    int check()
    {
        ll a = em, b = mh;
        if (md > e)
        {
            if (a >= (md-e))
                a-= md-e;
            else
                return 0;
        }
        if (md > m)
        {
            if (a >= (md-m))
                ;
            else
            {
                if (b >= (md-m-a))
                    b -= (md-m-a);
                else
                    return 0;
            }
        }
        if (b+h >= md) return 1;
        return 0;
    }
    ll maxSets(ll E, ll EM, ll M, ll MH, ll H)
    {
        ll bg = min(E, M, H), ed = INF;
        e = E; em = EM; m = M; mh = MH; h = H;
        while (bg < ed)
        {
            md = (bg+ed+1)>>1;
            if (check())
                bg = md;
            else
                ed = md-1;
        }
        return bg;
    }
};

500

Problem Statement

  Cat Snuke has learned that the number of ways to choose three things from x identical things is x(x-1)(x-2)/6. It means that the polynomial x(x-1)(x-2) is divisible by 6 for any integer x. He defined the greatest common divisor (GCD) of a nonzero polynomial P as the maximal integer d such that P(x) is always divisible by d for any integer x. For example, the GCD of P(x) = x(x-1)(x-2) is 6, because P(x) is always divisible by 6 and no bigger integer divides all P(x).

You want to compute the GCD of a polynomial P that is given as a product of many linear terms. You are given a string s that describes P. Construct P as follows: Start with P(x)=1 for all x. For each valid i, the character s[i] will be between '0' and '9', inclusive. Interpret it as a digit d[i] between 0 and 9, inclusive. Multiply P by the term (x-i)^d[i].

Compute the GCD of the polynomial P, and return it modulo 1,000,000,007.

Definition

 
Class: PolynomialGCD
Method: gcd
Parameters: string
Returns: int
Method signature: int gcd(string s)
(be sure your method is public)

Limits

 
Time limit (s): 2.000
Memory limit (MB): 256
Stack limit (MB): 256

Constraints

- s will contain between 1 and 10,000 characters, inclusive.
- Each character in s will be between '0' and '9', inclusive.

Examples

0)  
 
"111"
Returns: 6
P(x) = x(x-1)(x-2). The GCD of this polynomial is 6 as written in the statement.
1)  
 
"00000"
Returns: 1
P(x) = 1.
2)  
 
"2014"
Returns: 16
P(x) = (x-0)^2 * (x-1)^0 * (x-2)^1 * (x-3)^4 = x^2 * (x-2) * (x-3)^4.
3)  
 
"31415926535"
Returns: 659897170

非常有意思的一题,实际难度比1000分的还恶心

一个多项式 P(x) = (x-0)^a0 * (x-1)^a1 * (x-2)^a2 * ....*(x-n)^an  {P(x) >= 0}

求一个最大的数 GCD 使 P(x) % GCD==0 恒成立 

因为GCD = s0^b0 * s1^b1 *......{si 为素数},所以该题等价于对于素数s,找出使 P(x)%(s^b) == 0成立的最大b

那么在P(x)中,若 (x-c) % s == 0,则(x-c)^ac * (x-c+s)^a(c-s)*...*(x-c+s*k)^a(c-s*k) % s == 0 {c-s*k <= n,0<=c<=n},在当前情况下 b至少为ac + a(c-s) + ... +a(c-s*k),

为什么说是至少?因为还要考虑 s的指数次方的情况,该情况求解与上面类似,详见代码。

但c的值是不唯一的,所以要枚举c,求出d的集合,找出d的最小值

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rp(i,b) for(int i=(0);i<(b);++i)
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define repd(i,a,b) for(int i=(a);i<=(b);++i)
#define mst(a,b) memset(a,b,sizeof(a))
const int MAXN = 10005;
const ll mod = 1000000007;
int not_prime[MAXN], prim[MAXN],np;
int n;
void init_prime()
{
    rep(i,2,MAXN)
    {
        if (!not_prime[i]) prim[np++] = i;
        rp(j,np)
        {
            if ((i*prim[j]) >= MAXN) break;
            not_prime[i*prim[j]] = 1;
            if (i % prim[j] == 0) break;
        }
    }
}
inline ll mul(ll a, ll b)
{
    return a*b%mod;
}
ll m_pow(ll a, ll b)
{
    ll res = 1, p = a;
    while (b)
    {
        if (b & 1) res = mul(res, p);
        p = mul(p, p);
        b >>= 1;
    }
    return res;
}
int cal(vector<int> a, int p)
{
    int l = a.size(), res = int(mod);
    rp(i,p)
    {
        int sum = 0;
        vector<int> b;
        for (int j = i; j< l; j+= p) b.push_back(a[j]), sum += a[j];
        if ((int)b.size() >= p) sum += cal(b, p);
        res = min(res, sum);
    }
    return res;
}
class PolynomialGCD
{
public:
    PolynomialGCD(){init_prime();}
    int gcd(string s)
    {
        ll res = 1;
        vector<int> a;
        n = s.size();
        rp(i,n) a.push_back(s[i] - '0');
        repd(i,2,n)
        {
            if (not_prime[i]) continue;
            int c = cal(a, i);
            res = mul(res, m_pow(i, c));
        }
        return (int)res;
    }
};

1000

Problem Statement

  Cat Snuke has an N times N chessboard. He is going to place K rooks numbered 0 through K-1 onto the chessboard. (Note that the rooks are distinguishable.)

Obviously, he cannot put two rooks onto the same square of the chessboard. There are some additional restrictions he also has to obey. You are given these in a vector <string> graph with K elements, each containing K characters. For each i and j, graph[i][j] is either '1' or '0'. If graph[i][j] is '1', rooks i and j must be in the same row or column. If graph[i][j] is '0', rooks i and j must be neither in the same row, nor in the same column.

You are given the int N and the vector <string> graph. Return the number of ways to place the rooks, modulo 1,000,000,007.

Definition

 
Class: RookGraph
Method: countPlacements
Parameters: int, vector <string>
Returns: int
Method signature: int countPlacements(int N, vector <string> graph)
(be sure your method is public)

Limits

 
Time limit (s): 2.000
Memory limit (MB): 256
Stack limit (MB): 256

Constraints

- N will be between 1 and 50, inclusive.
- graph will contain between 1 and 50 elements, inclusive.
- Each element of graph will contain exactly K characters, where K is the number of elements of graph.
- Each character in graph will be either '0' or '1'.
- For each i, the i-th character of the i-th element of graph will be '1'.
- For each i and j, the j-th character of the i-th element of graph and the i-th character of the j-th element of graph will be the same.

Examples

0)  
 
8
{"11",
 "11"}
Returns: 896
There are 64 ways to put rook 0, and for each possible position of rook 0 there are 14 ways to put rook 1. Thus, the answer is 64 * 14 = 896.
1)  
 
8
{"111",
 "110",
 "101"}
Returns: 6272
2)  
 
2
{"11111",
 "11111",
 "11111",
 "11111",
 "11111"}
Returns: 0
The board is too small for 5 rooks.
3)  
 
10
{"1010000100",
 "0100101000",
 "1011010100",
 "0011010000",
 "0100100000",
 "0011010010",
 "0100001001",
 "1010000110",
 "0000010110",
 "0000001001"}
Returns: 289151874
4)  
 
50
{"10111110000",
 "01011010000",
 "10100010011",
 "11010110001",
 "11001100101",
 "10011100110",
 "11110011111",
 "00000011100",
 "00001111100",
 "00100110010",
 "00111010001"}
Returns: 0
5)  
 
31
{"10000000000000000000000000000000000000000000000000",
 "01000000000000000000000000000000000010000000010000",
 "00100000000010000000000100001100000000010010000000",
 "00010000000010000000001000000000000000000000000000",
 "00001000000000000000000000000000000000100000000000",
 "00000100101000000010000000000000000000100100000001",
 "00000010000000000100000001000000000000000000000001",
 "00000001000000001000000000000000000000000000000100",
 "00000100101000000000000000000000000000000000000001",
 "00000000010000000000000010000010000000000000100000",
 "00000100101000000000000000000010000000000000000001",
 "00000000000100000010000100001000000001001000100000",
 "00110000000010000000001000001000000000000010000000",
 "00000000000001000000000000000000000000000000000000",
 "00000000000000100000000000000000001010000000000010",
 "00000000000000010000000000100000000000000000000000",
 "00000001000000001000000000000000000000010000000000",
 "00000010000000000100000001000000010000000000000000",
 "00000100000100000010000000001000000001101100000000",
 "00000000000000000001000000000001000000000000001100",
 "00000000000000000000110000000000100000000000000010",
 "00000000000000000000110010000000100000000010000000",
 "00010000000010000000001000000001000000000001000000",
 "00100000000100000000000100000100000000010000100000",
 "00000000010000000000010011000000000000000010000000",
 "00000010000000000100000011000000000000000000000000",
 "00000000000000010000000000100000001000001000000000",
 "00000000000000000000000000010000010100000000000000",
 "00100000000110000010000000001000000001001010000000",
 "00100000000000000000000100000100000000010000000000",
 "00000000011000000000000000000010000000000000100000",
 "00000000000000000001001000000001000000000001001100",
 "00000000000000000000110000000000100100000000000000",
 "00000000000000000100000000010000010000000000000000",
 "00000000000000100000000000100000001000001000000000",
 "00000000000000000000000000010000100100000000000000",
 "01000000000000100000000000000000000010000000010010",
 "00000000000100000010000000001000000001001000000000",
 "00001100000000000010000000000000000000100100000000",
 "00100000000000001000000100000100000000010000000000",
 "00000000000100000010000000101000001001001000000000",
 "00000100000000000010000000000000000000100100000000",
 "00100000000010000000010010001000000000000010000000",
 "00000000000000000000001000000001000000000001000000",
 "00000000010100000000000100000010000000000000100000",
 "01000000000000000000000000000000000010000000010000",
 "00000000000000000001000000000001000000000000001100",
 "00000001000000000001000000000001000000000000001100",
 "00000000000000100000100000000000000010000000000010",
 "00000110101000000000000000000000000000000000000001"}
Returns: 0


略微有点烧脑洞的题,题意很清晰就不解释了

我的解法是,先用深搜找出相关联的点集(点集内每个点与点集内至少一个点存在共行或列)所占用的行数和列数,那么用这些行数和列数去拼凑(类似于可旋转的),得出最终分配方案的总行数和总列数。因为行和列是互不相关的,所以再对其各自排列组合一下

#include <cstdio>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rp(i,b) for(int i=(0);i<(b);++i)
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define repd(i,a,b) for(int i=(a);i<=(b);++i)
#define mst(a,b) memset(a,b,sizeof(a))
const int MAXN = 55;
const ll mod = 1000000007;
int m, g[MAXN][MAXN], n, istkn[MAXN][MAXN], ct[2][MAXN], ok;
typedef int TA[2];
struct _point
{
    int x, y;
} pt[MAXN];
TA ap[MAXN];
_point get_next(int p)
{
    rp(i,n)rp(j,n)if (!istkn[i][j])
    {
        int flg = 1;
        rp(k,m)
        {
            if (pt[k].x == -1) continue;
            if (g[p][k])
            {
                if (i!=pt[k].x && j != pt[k].y)
                {
                    flg = 0;
                    break;
                }
            }
            else
            {
                if (i==pt[k].x || j == pt[k].y)
                {
                    flg = 0;
                    break;
                }
            }
        }
        if (flg) return {i,j};
    }
    return {-1,-1};
}
int vis[MAXN];
void dfs(int x)
{
    if (!ok) return;
    vis[x] = 1;
    _point res = get_next(x);
    if (res.x == -1)
    {
        ok = 0;
        return;
    }
    istkn[res.x][res.y] = 1;
    ct[0][res.x] = 1;
    ct[1][res.y] = 1;
    pt[x] = res;
    rp(i,m)
    {
        if (g[x][i] && !vis[i])
            dfs(i);
    }
}
int cnt = 0;
ll sum, AA[MAXN];
void tfs(int dx, int lx, int ly)
{
    if (dx == cnt)
    {
        sum = (sum+AA[lx]%mod*AA[ly]%mod)%mod;
        return;
    }
    if (ap[dx][0] == ap[dx][1] && ap[dx][0] == 1)
    {
        if (lx+1<=n && ly+1<=n)
            tfs(dx+1, lx+1, ly+1);
        return;
    }
    rp(i,2)
    {
        if (lx+ap[dx][i]<=n && ly+ap[dx][1-i]<=n)
            tfs(dx+1, lx+ap[dx][i], ly+ap[dx][1-i]);
    }
}
class RookGraph
{
public:
    void init()
    {
        AA[0] = 1ll;
        rep(i,1,MAXN) AA[i] = AA[i-1]*(n-i+1)%mod;
    }
    int countPlacements(int N, vector <string> graph)
    {
        sum = 0ll;
        cnt = 0;
        ok = 1;
        m = (int)graph.size();
        n = N;
        if (N*N < m)
            return 0;
        init();
        rp(i,m) rp(j,i)
            g[i][j] = g[j][i] = graph[i][j] - '0';
        mst(vis, 0);
        rp(i,m)
        {
            if (vis[i]) continue;
            mst(ct, 0);
            mst(pt, -1);
            mst(istkn, 0);
            dfs(i);
            if (!ok) return 0;
            int lx = 0, ly = 0;
            rp(j,n) lx += ct[0][j], ly += ct[1][j];
            ap[cnt][0] = lx;
            ap[cnt++][1] = ly;
        }
        tfs(0, 0, 0);
        return sum;
    }
};



你可能感兴趣的:(TopCoder SRM 657 DIV 1)