TopCoder SRM 657 DIV 1
2015-05-01 14:47
288 查看
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 | ||||||||||||
| ||||||||||||
Limits | ||||||||||||
| ||||||||||||
Constraints | ||||||||||||
- | E, EM, M, MH, H will be between 0 and 1,000,000,000,000,000,000 (10^18), inclusive. | |||||||||||
Examples | ||||||||||||
0) | ||||||||||||
| ||||||||||||
1) | ||||||||||||
| ||||||||||||
2) | ||||||||||||
| ||||||||||||
3) | ||||||||||||
| ||||||||||||
4) | ||||||||||||
|
#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 | ||||||||||||
| ||||||||||||
Limits | ||||||||||||
| ||||||||||||
Constraints | ||||||||||||
- | s will contain between 1 and 10,000 characters, inclusive. | |||||||||||
- | Each character in s will be between '0' and '9', inclusive. | |||||||||||
Examples | ||||||||||||
0) | ||||||||||||
| ||||||||||||
1) | ||||||||||||
| ||||||||||||
2) | ||||||||||||
| ||||||||||||
3) | ||||||||||||
|
一个多项式 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 | ||||||||||||
| ||||||||||||
Limits | ||||||||||||
| ||||||||||||
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) | ||||||||||||
| ||||||||||||
1) | ||||||||||||
| ||||||||||||
2) | ||||||||||||
| ||||||||||||
3) | ||||||||||||
| ||||||||||||
4) | ||||||||||||
| ||||||||||||
5) | ||||||||||||
|
我的解法是,先用深搜找出相关联的点集(点集内每个点与点集内至少一个点存在共行或列)所占用的行数和列数,那么用这些行数和列数去拼凑(类似于可旋转的),得出最终分配方案的总行数和总列数。因为行和列是互不相关的,所以再对其各自排列组合一下
#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 Div2 Problem 1000 - PolynomialRemainder(数学)
- TopCoder SRM 657 Div2 Problem 500 - ProblemSetsEasy (二分 + 模拟)
- topcoder SRM 624 DIV2 CostOfDancing
- topcoder SRM 618 DIV2 WritingWords
- TopCoder 250 points 28-SRM 157 DIV 2 185.60/250 74.24%
- Topcoder SRM 626 DIV2 SumOfPower
- TopCoder SRM 543 DIV2
- [TopCoder] SRM580, DIV1, 600p, Solution
- topcoder srm 705 div1 -3
- Topcoder SRM 144 Div1 550(数学和dp问题求方案数,很有意思)
- topcoder srm 440 div1
- Topcoder SRM 562 DIV2 900 RandomOption
- topcoder-srm-233-div2
- topcoder srm 450 div1
- TopCoder SRM 360 DIV2 500 分题目, 需要排列组合么?需要强力法么?
- Topcoder SRM 663 Div2 Hard: CheeseRolling(状压DP)
- topcoder srm 661 div1 -3
- topcoder srm 694 div1 -3
- Topcoder SRM 660 DIV1 500 Privateparty(数学,容斥)
- topcoder srm 715 div1 -23