标签:
给出一个四边形四条边
通过余弦定理考察
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: A.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-09
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const double eps = 1e-10;
int sgn(double x) { return x < -eps? -1: x > eps; }
inline double cosf(double a, double b, double c)
{ return (a * a + b * b - c * c) / (2 * a * b); }
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
int ab, cd, ad, bc, ac, bd;
scanf("%d%d%d%d%d%d", &ab, &cd, &ad, &bc, &ac, &bd);
printf("Case #%d: %s\n", ++cas, !sgn(cosf(ac, bc, ab)
- cosf(ad, bd, ab))? "Yes": "No");
}
return 0;
}
构造一个
由于共有
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: B.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-09
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
if (n < 4 || (n & 1)) {
printf("Case #%d: No\n", ++cas);
} else {
printf("Case #%d: Yes\n", ++cas);
For(i,1,n) {
printf("%d %d\n", i, i == n? 1: i + 1);
if (i <= n / 2) printf("%d %d\n", i, i + n / 2);
}
}
}
return 0;
}
用K种颜色对长度为N的环涂色,问考虑旋转同构下本质不同的涂色方案有多少种
由Pólya定理可知,答案等于
对于
所以上式化简为
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: C.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-09
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int mod = 1000000007;
int n, k, ret;
vector<Pii> fct;
int pow_mod(int a, int b)
{
int ret = 1;
for (; b; a = (LL)a * a % mod, b >>= 1)
if (b & 1) ret = (LL)ret * a % mod;
return ret;
}
void decomp(int n)
{
fct.clear();
for (int i = 2; i * i <= n; ++i) if (n % i == 0) {
fct.push_back(Pii(i, 0));
while (n % i) ++fct.back().second, n /= i;
}
if (n > 1) fct.push_back(Pii(n, 1));
}
void dfs(int i, int gcd, int phi)
{
if (i == fct.size()) {
ret = (ret + (LL)pow_mod(k, gcd) * phi) % mod;
return;
}
dfs(i + 1, gcd, phi);
phi *= fct[i].first - 1;
rep(j,fct[i].second) {
gcd /= fct[i].first;
dfs(i + 1, gcd, phi);
phi *= fct[i].first;
}
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &k);
decomp(n);
ret = 0;
dfs(0, n, 1);
ret = (LL)ret * pow_mod(n, mod - 2) % mod;
printf("Case #%d: %d\n", ++cas, ret);
}
return 0;
}
问用
将最后一维当作时间考虑可以发现,在某一时刻,前三维构成
对于每次转移,要么将两个相邻的0置1,要么将状态取反后到达下一时刻
我们可以先预处理构成某个状态的方案数
对于第一种转移,
考虑相邻时刻的转移,
当然,实际情况中我们枚举
上面的DP已经可以算出正确答案,但状态
考虑对于某个状态,可以通过旋转/对称进行归类
再考察初始状态能到达的状态,我们得到有效状态只有997个,但仍然无法用矩阵快速幂求解
通过某种方式可以证明(然而我并不懂),答案是关于
即
我们可以用上面的方法暴力算出前
通过
后面由于是常系数齐次线性递推关系,可以用叉姐论文《线性递推关系与矩阵乘法》中的方法求解
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: D.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-09
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxs = (1 << 16) + 5;
const int maxt = 2452 + 5; // max normalized states
const int maxc = 997 + 5; // max reachable states
const int maxm = 921 + 5; // max coefficient of linear recurrence
const int mod = 1000000007;
int rot[] = {4, 1, 8, 2};
int rotate(int S)
{
int ret = 0;
for (int p = 0; p < 16; p += 4)
rep(i,4) if ((S >> p) & (1 << i)) ret |= rot[i] << p;
return ret;
}
int flip(int S, int f)
{
int ret = 0, mask = (f & 4) << 1 | f;
rep(i,16) if (S & (1 << i)) ret |= 1 << (i ^ mask);
return ret;
}
int norm(int S)
{
int ret = S;
rep(pos,16) {
int T = flip(S, pos >> 1);
ret = min(ret, pos & 1? rotate(T) :T);
}
return ret;
}
void gcd(int a, int b, int &g, int &x0, int &y0)
{
if (!b) g = a, x0 = 1, y0 = 0;
else gcd(b, a % b, g, y0, x0), y0 -= x0 * (a / b);
}
int inv(int a)
{
int g, x0, y0;
gcd(a, mod, g, x0, y0);
return (x0 + mod) % mod;
}
int gauss(int a[][maxm], int n, int ret[])
{
int rank = 0;
bool free[maxc];
memset(free, true, sizeof(free));
rep(i,n) {
int r = rank;
while (r < n && !a[r][i]) ++r;
if (r == n) continue;
if (r != rank) For(j,i,n) swap(a[r][j], a[rank][j]);
for (int k = rank + 1; k < n; ++k) {
int tmp = (LL)a[k][i] * inv(a[i][i]) % mod;
for (int j = n; j >= i; --j) a[k][j] = (a[k][j] -
(LL)tmp * a[rank][j] % mod + mod) % mod;
}
++rank, free[i] = false;
}
for (int i = rank; i < n; ++i) if (a[i][n]) return -1;
for (int i = n - 1, k = rank; i >= 0; --i) if (!free[i]) {
ret[i] = a[--k][n];
for (int j = i + 1; j < n; ++j) ret[i] = (ret[i] -
(LL)a[k][j] * ret[j] % mod + mod) % mod;
ret[i] = (LL)ret[i] * inv(a[k][i]) % mod;
}
return rank;
}
int id[maxs];
int sta[maxt], tot;
int f[maxs];
int t[maxt][maxt];
bool vis[maxt];
int que[maxc], head, tail;
int g[2][maxc];
int m = 921;
int A[maxm][maxm], r[maxm];
int a[] = {121, 155969, 127027769, 249680610}; // 744708554, 4538468, ...
int k[] = {1731, 999029836, 191946633, 890219327}; // 540076999, 678513135, ...
void init()
{
int ALL = (1 << 16) - 1;
// find normalized states
memset(id, -1, sizeof(id));
For(T,0,ALL) if (~__builtin_popcount(T) & 1) {
int S = norm(T);
if (~id[S]) id[T] = id[S];
else id[S] = tot, sta[tot++] = S;
}
// calc number of constructing state S from state 0
f[0] = 1;
rep(k,4) rep(j,2) rep(i,2) {
int p = (k << 2) | (j << 1) | i;
For(S,0,ALL) if (~id[S] && (~S & (1 << p))) {
if (k < 3 && (~S & (16 << p))) f[S|17<<p] += f[S];
if (j < 1 && (~S & (4 << p))) f[S|5<<p] += f[S];
if (i < 1 && (~S & (2 << p))) f[S|3<<p] += f[S];
}
}
// calc transfer coefficient of normalized states
rep(i,tot) {
int S = sta[i] ^ ALL;
for (int T = S;; T = (T - 1) & S) {
if (~id[T]) t[i][id[(sta[i]|T)^ALL]] += f[T];
if (!T) break;
}
}
// keep states which can be reached from state 0
vis[0] = true, que[tail++] = 0;
while (head < tail) {
int i = que[head++];
rep(j,tot) if (t[i][j] && !vis[j])
vis[j] = true, que[tail++] = j;
}
// calc coefficient matrix of gauss
g[1][0] = 1;
rep(i,m*2) {
int o = i & 1;
memset(g[o], 0, sizeof(g[o]));
rep(j,tail) rep(k,tail) g[o][j] = (g[o][j] +
(LL)(g[o^1][k] * t[que[k]][que[j]])) % mod;
if (i <= m) {
A[0][i] = g[o][0];
} else {
rep(j,m) A[i-m][j] = A[i-m-1][j+1];
A[i-m][m] = g[o][0];
}
}
assert(~gauss(A, m, r));
FILE *fout = fopen("D.arg", "w");
rep(i,m) fprintf(fout, "%s%d", i? ", ": "int a[] = {", A[0][i]);
fprintf(fout, "};\n");
rep(i,m) fprintf(fout, "%s%d", i? ", ": "int k[] = {", r[m-i-1]);
fprintf(fout, "};\n");
fclose(fout);
}
void multiply(int u[], int v[])
{
static int t[maxm*2];
memset(t, 0, sizeof(t));
rep(i,m) rep(j,m) t[i+j] = (t[i+j] + (LL)u[i] * v[j]) % mod;
for (int i = 2 * m - 2; i >= m; --i) {
rep(j,m) t[i-j-1] = (t[i-j-1] + (LL)k[j] * t[i]) % mod;
t[i] = 0;
}
memcpy(u, t, sizeof(t));
}
int calc(int n)
{
static int u[maxm*2], v[maxm*2];
memset(u, 0, sizeof(u)), u[0] = 1;
for (int p = 1; n; p <<= 1, n >>= 1) {
if (p < m) memset(v, 0, sizeof(v)), v[p] = 1;
else multiply(v, v);
if (n & 1) multiply(u, v);
}
int ret = 0;
rep(i,m) ret = (ret + (LL)u[i] * a[i]) % mod;
return ret;
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
// init();
while (T--) {
int n;
scanf("%d", &n);
printf("Case #%d: %d\n", ++cas, calc(n - 1));
}
return 0;
}
对于初始为0的
首先想到,最终的期望等于每一步失败概率的累加和
考虑用二进制表示当前矩阵的状态,其中全为1的子矩阵个数为k,0的个数为
如果要保证该状态不变,则每次只能选择这k个子矩阵中的某个涂色,概率
由容斥原理,该状态对于失败概率的贡献为
不难发现,对结果有影响的只有
令
则向
计算答案时枚举某一列存在0的状态,令后面的列全为1,重新计算
根据
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: E.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-10
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 20 + 1;
const int maxk = 3 * 20 * (20 + 1) / 2 + 1;
long double f[maxn][maxn][maxn][maxk][2];
inline int C(int n) { return 3 * n * (n + 1) / 2; }
void init()
{
memset(f, 0, sizeof(f)), f[0][0][0][0][0] = 1;
For(i,0,19) For(u,0,i) For(v,0,i) For(k,0,C(i)) rep(o,2) {
f[i+1][0][0][k][o] += f[i][u][v][k][o];
f[i+1][u+1][0][k+u+1][o^1] += f[i][u][v][k][o];
f[i+1][0][v+1][k+v+1][o^1] += f[i][u][v][k][o];
f[i+1][u+1][v+1][k+u+v+min(u,v)+3][o] += f[i][u][v][k][o];
}
}
double solve(int n)
{
long double ret = 0;
For(i,0,n) For(u,0,i) For(v,0,i) if (!u || !v) For(k,0,C(i)) {
int c = k + u * (n - i) + v * (n - i) + C(n - i);
if (c == C(n)) continue;
ret += f[i][u][v][k][1] / (1 - (long double)c / C(n));
ret -= f[i][u][v][k][0] / (1 - (long double)c / C(n));
}
return ret;
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
init();
while (T--) {
int n;
scanf("%d", &n);
printf("Case #%d: %.6f\n", ++cas, solve(n));
}
return 0;
}
有
转账时银行按比例收取手续费,问最后每个人最多能有多少钱
二分答案,考察超过
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: F.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-10
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const double eps = 1e-10;
int sgn(double x) { return x < -eps? -1: x > eps; }
const int maxn = 100000 + 5;
int n;
double k, a[maxn];
bool check(double b)
{
double ret = 0;
rep(i,n) {
if (a[i] < b) ret -= (b - a[i]);
if (a[i] > b) ret += (a[i] - b) * (1 - k);
}
return sgn(ret) >= 0;
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d%lf", &n, &k);
double l = 0, r = 0;
rep(i,n) scanf("%lf", &a[i]), r += a[i];
r /= n;
while (sgn(l - r) < 0) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
printf("Case #%d: %.6f\n", ++cas, l);
}
return 0;
}
Alice和Bob玩游戏,Bob有一个可以按照设定的概率随机输出
如果Alice猜对生成的数,则Alice赢1元钱
如果Alice猜的是生成的数减1,则Bob赢1元钱
问Bob在设置最优的概率,同时Alice选择最优策略的条件下,Alice赢钱的期望为多少
若生成器输出
显然Alice会选择概率下降最大的数,而Bob则要最小化这一值
不难发现,当所有概率下降的值相同,即
通过方程解得,答案为
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: G.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-10
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
printf("Case #%d: %.6f\n", ++cas, 2.0 / n / (n + 1));
}
return 0;
}
输入
换个方向思考,先枚举
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: H.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-10
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 1000000 + 5;
const int mod = 1000000007;
int pow_mod(int a, int b)
{
int ret = 1;
for (; b; a = (LL)a * a % mod, b >>= 1)
if (b & 1) ret = (LL)ret * a % mod;
return ret;
}
bool isp[maxn];
int prime[maxn], sz;
int mu[maxn];
int f[maxn], pre[maxn], sum[maxn];
void init()
{
memset(isp, true, sizeof(isp));
isp[0] = isp[1] = false, mu[1] = 1;
for (int i = 2; i < maxn; ++i) {
if (isp[i]) prime[sz++] = i, mu[i] = -1;
for (int j = 0; j < sz && prime[j] * i < maxn; ++j) {
isp[prime[j]*i] = false;
if (i % prime[j] == 0) {
mu[prime[j]*i] = 0;
break;
}
mu[prime[j]*i] = mu[prime[j]] * mu[i];
}
}
for (int d = 1; d < maxn; ++d) {
int k = (mu[d] * pow_mod(d, mod - 2) + mod) % mod;
for (int i = 1; d * i < maxn; ++i) f[d*i] = (f[d*i] + k) % mod;
}
rep(i,maxn) if (i) {
f[i] = (LL)f[i] * pow_mod(i, 5) % mod;
pre[i] = (pre[i-1] + f[i]) % mod;
sum[i] = (sum[i-1] + (LL)i * i) % mod;
}
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
init();
while (T--) {
int n, m, ret = 0;
scanf("%d%d", &n, &m);
for (int d = 1, nd; d <= n && d <= m; d = nd + 1) {
nd = min(n / (n / d), m / (m / d));
ret = (ret + (LL)(pre[nd] - pre[d-1] + mod) *
sum[n/d] % mod * sum[m/d]) % mod;
}
printf("Case #%d: %d\n", ++cas, ret);
}
return 0;
}
输入
“点”按1单位时间
“线”按3单位时间
元素间空1个单位
字母间空3个单位
单词间空7个单位
按下输出’=’,空白输出’.’
按照上面说的模拟…
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: I.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-10
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
string code[] = {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.",
"....", "..", ".---", ".-.-", ".-..", "--", "-.",
"---", ".--.", "--.-", ".-.", "...", "-",
"..-", "...-", ".--", "-..-", "-.--", "--..",
".----", "..---", "...--", "....-", ".....",
"-....", "--...", "---..", "----.", "-----"
};
void print(char ch)
{
int v = (isalpha(ch)? tolower(ch) - ‘a‘: 26 + (ch - ‘0‘ + 9) % 10);
rep(i,code[v].length()) {
if (i) putchar(‘.‘);
printf("%s", code[v][i] == ‘.‘? "=": "===");
}
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
printf("Case #%d: ", ++cas);
rep(i,n) {
if (i) rep(j,7) putchar(‘.‘);
char buf[32];
scanf("%s", buf);
for (int j = 0; buf[j]; ++j) {
if (j) rep(k,3) putchar(‘.‘);
print(buf[j]);
}
}
puts("");
}
return 0;
}
问大小为
DFS
对于某棵子树计算其左子树的大小
与当前的k比较以选择进入的分支
进入右子树时注意更新k的值
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: J.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-10
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
int dfs(int v, int n, int k)
{
int p = 1;
while (p * 2 <= n) p *= 2;
int l = p / 2 - 1 + min(n - (p - 1), p / 2);
if (n == 1 || k == l + 1) return v;
return k <= l? dfs(v * 2, l, k): dfs(v * 2 + 1, n - l - 1, k - l - 1);
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
int n, k;
scanf("%d%d", &n, &k);
printf("Case #%d: %d\n", ++cas, dfs(1, n, k));
}
return 0;
}
输入
显然这个序列由
/**
* Copyright ? 2016 Authors. All rights reserved.
*
* FileName: K.cpp
* Author: Beiyu Li <sysulby@gmail.com>
* Date: 2016-05-10
*/
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
int n, f[3];
scanf("%d%d%d", &f[0], &f[1], &n);
f[2] = f[0] ^ f[1];
printf("Case #%d: %d\n", ++cas, f[n%3]);
}
return 0;
}
GDCPC2016题解 by lby@SYSU | Asiimov
标签:
原文地址:http://blog.csdn.net/u010929036/article/details/51365598