bfs
#include
#include
#include
#include
class Graph {
int n;
std::vector<std::vector<int>> es;
public:
Graph (int n_): n(n_), es(n) {}
void adde (int a, int b) {
es[a].push_back(b);
}
bool bfs (int ibeg, int iend) {
auto vis = std::vector<char>(n, 0);
auto q = std::queue<int>();
q.push(ibeg);
vis[ibeg] = true;
while (!q.empty()) {
int c = q.front();
q.pop();
for (int nxt: es[c])
if (!vis[nxt]) {
vis[nxt] = true;
q.push(nxt);
}
}
return vis[iend];
}
};
struct Sensor {
int x, y, s;
bool conn (Sensor const &rhs) const {
int dx = x - rhs.x;
int dy = y - rhs.y;
int ss = s + rhs.s;
return dx * dx + dy * dy <= ss * ss;
}
};
int main () {
std::ios::sync_with_stdio(false);
int n, m, k;
std::cin >> n >> m >> k;
auto v = std::vector<Sensor>(k);
for (auto &c: v)
std::cin >> c.x >> c.y >> c.s;
bool orz = false;
auto g = Graph(n + 2);
for (int i = 0; i < k; ++i)
for (int j = 0; j < i; ++j)
if (v[i].conn(v[j])) {
g.adde(i, j);
g.adde(j, i);
}
for (int i = 0; i < k; ++i) {
auto &c = v[i];
if (c.x <= c.s || c.y >= m - c.s)
g.adde(n, i);
if (c.x >= n - c.s || c.y <= c.s)
g.adde(i, n + 1);
if (c.conn(Sensor { 0, 0, 0 }) || c.conn(Sensor { n, m, 0 })) {
orz = true;
break;
}
}
if (!orz)
orz = g.bfs(n, n + 1);
std::cout << (orz ? "N\n" : "S\n");
return 0;
}
#include
#include
int main () {
int n;
std::cin >> n;
int x;
std::cin >> x;
bool orz = false;
for (int i = 1; i < n; ++i) {
int t;
std::cin >> t;
if (t > x)
orz = true;
}
std::cout << (orz ? "N\n" : "S\n");
return 0;
}
长链剖分,这个题的带修版本在comet oj上有,叫做黄金啥的。。。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int const N = 100005;
int dep[N];
vector<int> G[N];
int n, m;
int fa[N];
int son[N];
int len[N];
void dfs(int x) {
for (auto y : G[x]) {
dep[y] = dep[x] + 1;
dfs(y);
if (len[y] > len[x]) {
len[x] = len[y];
son[x] = y;
}
}
len[x]++;
}
vector<int> ans;
void dfs2(int x, int t) {
if (G[x].size() == 0u) {
ans.push_back(dep[x] - dep[t] + 1);
return;
}
if (son[x])
dfs2(son[x], t);
for (auto y : G[x]) {
if (y == son[x])
continue;
dfs2(y, y);
}
}
int main() {
ios::sync_with_stdio(0);
cin >> n >> m;
for (int i = 2; i <= n; ++i) {
cin >> fa[i];
G[fa[i]].push_back(i);
}
dfs(1);
dfs2(1, 1);
sort(ans.begin(), ans.end());
reverse(ans.begin(), ans.end());
int sum = 0;
for (int i = 0; i < min(m, (int)ans.size()); ++i)
sum += ans[i];
cout << sum << '\n';
}
非常的有趣。
表示不会做然后看了别人的代码。
容易发现,对于一个鱼缸,显然你要么把公的全部拿出去,变回母的再拿回来(当然如果是变成母的就完成了那就不用拿回来了),或者是把所有母的都拿出去,留下公的变一条拿走一条。
因为容器的问题,所以不能是所有的鱼缸都是同一种拿出去的方式。
然后呢,因为变成母的之后完成了就不用拿回来,所以这里的天数还和空的有多少个有关。
但是注意到空鱼缸是可以能放就放的,而且是哪个鱼缸放过去并不影响。
所以你就 f [ i ] [ j ] [ k ] [ l ] f[i][j][k][l] f[i][j][k][l]表示到了第 i i i个鱼缸,现在有 j j j个空鱼缸还未放鱼,其中 k , l k,l k,l分别表示两种操作是否被使用。
注意到 j j j在中途可能为负数,故需要开到 2 N 2N 2N,但是这样就MLE了,再滚动一下就行。
所以这里具体到这个代码来说, j j j的意义实际上是,如果 j > = n j>=n j>=n,表示有 j − n j-n j−n个空鱼缸可以使用,如果 j < n j
#include
#include
#include
#include
#include
using namespace std;
template<typename T, typename U>
inline void Remin(T& a, U const& b) {
a = b < a ? b : a;
}
int const N = 3005;
int f[2][N << 1][2][2];
int n;
int mel[N], fem[N];
int main() {
ios::sync_with_stdio(0);
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> mel[i] >> fem[i];
bool is_all_empty = 1;
for (int i = 1; i <= n; ++i)
is_all_empty &= mel[i] == 0;
if (is_all_empty) {
cout << 0 << '\n';
return 0;
}
memset(f, 127 / 2, sizeof(f));
int INF = f[0][n][0][0];
f[0][n][0][0] = 0;
int now = 1;
for (int i = 1; i <= n; ++i, now ^= 1)
for (int j = 0; j <= n * 2; ++j)
for (int k1 = 0; k1 < 2; ++k1)
for (int k2 = 0; k2 < 2; ++k2) {
if (f[now ^ 1][j][k1][k2] == INF)
continue;
Remin(f[now][max(0, j - mel[i])][1][k2], f[now ^ 1][j][k1][k2] + mel[i] * 2);
Remin(f[now][j + (mel[i] == 0 && fem[i] == 0)][k1][1], f[now ^ 1][j][k1][k2] + mel[i] + fem[i] - 1);
f[now ^ 1][j][k1][k2] = INF;
}
int ans = INF;
for (int i = 0; i <= n; ++i)
ans = min(ans, f[now ^ 1][i][1][1]);
cout << ans << '\n';
}
费用流板子,只不过费用是小数而已
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
const double INF = 1e300;
const double EPS = 1e-10;
class Graph {
public:
struct E {
int to;
int f;
double w;
};
int n;
std::vector<E> es;
std::vector<std::vector<int>> nxt;
std::vector<std::pair<double, int>> dis;
std::vector<char> inq;
Graph (int n): n(n), es(), nxt(n), dis(n), inq(n) {}
void adde (int a, int b, int f, double w) {
// std::cerr << "+ " << a << "->" << b << " f=" << f << " w=" << w << "\n";
int idx = es.size();
es.push_back(E { b, f, w });
es.push_back(E { a, 0, -w });
nxt[a].push_back(idx);
nxt[b].push_back(idx + 1);
}
void spfa (int ibeg) {
for (int i = 0; i < n; ++i)
dis[i] = { INF, -1 };
for (int i = 0; i < n; ++i)
inq[i] = 0;
std::queue<int> q;
q.push(ibeg);
dis[ibeg] = { 0.0, -1 };
while (!q.empty()) {
int c = q.front();
q.pop();
inq[c] = false;
for (int idx: nxt[c]) {
auto &e = es[idx];
if (e.f && dis[e.to].first > dis[c].first + e.w + EPS) {
dis[e.to] = { dis[c].first + e.w, idx };
// std::cerr << "ext " << c << "->" << e.to << " =" << dis[e.to].first << "\n";
if (!inq[e.to]) {
inq[e.to] = true;
q.push(e.to);
}
}
}
}
}
void cost_flow (int ibeg, int iend) {
while (spfa(ibeg), dis[iend].second != -1) {
// std::cerr << dis[iend].first << '\n';
int f = std::numeric_limits<int>::max();
for (int i = iend; dis[i].second != -1; ) {
int idx = dis[i].second;
f = std::min(f, es[idx].f);
i = es[idx ^ 1].to;
}
for (int i = iend; dis[i].second != -1; ) {
int idx = dis[i].second;
es[idx].f -= f;
es[idx ^ 1].f += f;
i = es[idx ^ 1].to;
}
}
}
};
int main () {
std::ios::sync_with_stdio(false);
int n;
std::cin >> n;
auto g = Graph(n + n + 2);
int ibeg = n + n, iend = ibeg + 1;
for (int i = 0; i < n; ++i) {
g.adde(ibeg, i, 1, 0);
g.adde(n + i, iend, 1, 0);
}
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) {
int x;
std::cin >> x;
double w = log((double)x);
g.adde(i, n + j, 1, -w);
}
g.cost_flow(ibeg, iend);
auto ans = std::vector<int>(n);
for (int i = 0; i < n; ++i)
for (int idx: g.nxt[i])
if (g.es[idx].f == 0) {
// ans[i] = g.es[idx].to - n;
ans[g.es[idx].to - n] = i;
break;
}
for (int x: ans)
std::cout << x + 1 << ' ';
std::cout << '\n';
return 0;
}
#include
#include
using namespace std;
int main() {
int n, m;
cin >> n >> m;
long long s = n * m;
for (int i = 1; i <= 9; ++i) {
cout << (s * i + 9) / 10;
if (i == 9)
cout << '\n';
else
cout << ' ';
}
}
显然考虑floyed,但是这里是要求不包括起点和终点的路径上的点权要第K大/小
那么就按温度依次把点拿来当中间点来更新所有点就行。
这里的题意有点emmmmmm
补题的时候看了clar才发现真相x
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define SZ(x) ((int)(x).size())
using pii = pair<int, int>;
int const N = 405;
int const M = 100005;
int const INF = 1e9;
int g[N][N];
int n, m;
int ans[M];
struct ques {
int x, y;
int K;
int id;
bool operator < (ques const& oth) const {
return K < oth.K;
}
};
vector<ques> que[2];
int qn;
int T[N];
int id[N];
void solve(vector<ques>& q) {
sort(q.begin(), q.end());
int p = 0;
static int f[N][N];
memcpy(f, g, sizeof(f));
int tp = 0;
for (int i = 1; i <= n; ++i) {
int now = id[i];
for (int j = 1; j <= n; ++j)
for (int k = 1; k <= n; ++k)
f[j][k] = min(f[j][k], f[j][now] + f[now][k]);
if (i == n || T[id[i]] != T[id[i + 1]]) {
++tp;
while (p < SZ(q) && (q[p].K == tp || i == n)) {
ans[q[p].id] = f[q[p].x][q[p].y];
++p;
}
}
}
}
int main() {
ios::sync_with_stdio(0);
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> T[i];
id[i] = i;
}
sort(id + 1, id + n + 1, [=] (int const& x, int const& y) {
return T[x] < T[y];
});
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
g[i][j] = INF;
for (int i = 1; i <= m; ++i) {
int x, y, w;
cin >> x >> y >> w;
g[x][y] = g[y][x] = w;
}
cin >> qn;
for (int i = 0; i < qn; ++i) {
int x, y, K, op;
cin >> x >> y >> K >> op;
que[op].push_back({ x, y, K, i });
}
solve(que[0]);
reverse(id + 1, id + n + 1);
solve(que[1]);
for (int i = 0; i < qn; ++i)
cout << (ans[i] >= INF ? -1 : ans[i]) << '\n';
}
模拟一下下。
#include
#include
#include
char stupid_ord[] = "A23456789DQJK";
const int N = sizeof stupid_ord - 1 + 2;
int ord[256];
int main () {
std::ios::sync_with_stdio(false);
for (int i = 0; stupid_ord[i]; ++i)
ord[(int)stupid_ord[i]] = i;
using Arr = std::array<char, N>;
int n, k;
std::cin >> n >> k;
auto v = std::vector<Arr>(n);
for (int i = 0; i < n; ++i) {
char s[5];
std::cin >> s;
for (int j = 0; j < 4; ++j) {
// std::cerr << "+card " << ord[(int)s[j]] << '\n';
++v[i][ord[(int)s[j]]];
}
}
auto is_win = [&](Arr const &arr) {
for (int i = 0; i < N - 2; ++i)
if (arr[i] == 4)
return true;
return false;
};
int cur = k - 1, win;
for (int i = 0; i < n; ++i)
if (i != cur && is_win(v[i])) {
std::cout << i + 1 << '\n';
return 0;
}
++v[cur][N - 1];
// int cnt = 0;
for (;;) {
// std::cerr << "cur=" << cur << '\n';
// for (int i = 0; i < N - 2; ++i)
// std::cerr << (int)v[cur][i] << ' ';
// std::cerr << '\n';
// if (++cnt == 5)
// return 1;
int nxt = (cur + 1) % n;
// int nxt = (cur - 1 + n) % n;
if (v[cur][N - 2]) {
// std::cerr << cur << "->" << nxt << " X\n";
--v[cur][N - 2];
++v[nxt][N - 1];
} else {
int imx = -1;
for (int i = 0; i < N - 2; ++i)
if (v[cur][i] && (imx == -1 || v[cur][i] < v[cur][imx]))
imx = i;
--v[cur][imx];
++v[nxt][imx];
// std::cerr << cur << "->" << nxt << " " << imx << "\n";
if (v[cur][N - 1]) {
// std::cerr << cur << " down\n";
--v[cur][N - 1];
++v[cur][N - 2];
}
}
if (is_win(v[cur])) {
win = cur;
break;
}
cur = nxt;
}
std::cout << win + 1 << '\n';
return 0;
}
苦推若干小时,最后大力上BM居然找出来了解。。。。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef vector<int> VI;
typedef long long LL;
typedef pair<int,int> PII;
const LL MOD = 1000000007;
LL KSM(LL a,LL k) {
LL ret=1; a%=MOD;
assert(k>=0);
while(k) {
if(k&1) ret=ret*a%MOD;
a=a*a%MOD;
k>>=1;
}
return ret;
}
int _;
LL n;
namespace linear_seq {
const int N = 10010;
LL res[N],base[N],_c[N],_md[N];
vector<LL> Md;
void mul(LL *a,LL *b, LL k) {
for(int i=0;i<k+k;i++) _c[i]=0;
for(int i=0;i<k;i++) if(a[i]) {
for(int j=0;j<k;j++) {
_c[i+j]=(_c[i+j]+a[i]*b[j])%MOD;
}
}
for(int i=k+k-1;i>=k;i--) if(_c[i])
for(int j=0;j<Md.size();j++) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%MOD;
for(int i=0;i<k;i++) a[i]=_c[i];
}
int solve(LL n,VI a,VI b) {
LL ans=0,pnt=0;
LL k=a.size();
assert(a.size()==b.size());
for(int i=0;i<k;i++) _md[k-1-i]=-a[i];
_md[k]=1;
Md.clear();
for(int i=0;i<k;i++) if(_md[i]!=0) Md.push_back(i);
for(int i=0;i<k;i++) res[i]=base[i]=0;
res[0]=1;
while((1ll<<pnt)<=n) pnt++;
for(LL p=pnt;p>=0;p--) {
mul(res,res,k);
if((n>>p)&1) {
for(int i=k-1;i>=0;i--) res[i+1]=res[i];
res[0]=0;
for(int j=0;j<Md.size();j++) {
res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%MOD;
}
}
}
for(int i=0;i<k;i++) ans=(ans+res[i]*b[i])%MOD;
if(ans<0) ans+=MOD;
return ans;
}
VI BM(VI s) {
VI C(1,1),B(1,1);
LL L=0,m=1,b=1;
for(int n=0;n<s.size();n++) {
LL d=0;
for(int i=0;i<=L;i++) d=(d+(LL)C[i]*s[n-i])%MOD;
if(d==0) m++;
else if(2*L<=n) {
VI T=C;
LL c=MOD-d*KSM(b,MOD-2)%MOD;
while(C.size()<B.size()+m) C.push_back(0);
for(int i=0;i<B.size();i++) {
C[i+m]=(C[i+m]+c*B[i])%MOD;
}
L=n+1-L;
B=T;
b=d;
m=1;
} else {
LL c=MOD-d*KSM(b,MOD-2)%MOD;
while(C.size()<B.size()+m) C.push_back(0);
for(int i=0;i<B.size();i++) {
C[i+m]=(C[i+m]+c*B[i])%MOD;
}
m++;
}
}
return C;
}
int gao(VI a,LL n) {
//VI c=BM(a);
//c.erase(c.begin());
//for(int i=0;i<((int)c.size());i++) c[i]=(MOD-c[i])%MOD;
VI c = { 6, -8 + MOD, -8 + MOD, 16 };
//reverse(c.begin(), c.end());
return solve(n,c,VI(a.begin(),a.begin()+((int)c.size())));
}
};
static bool vis[10][3];
void dfs(int x, int y, int& ans, int sum) {
if (!(1 <= x && x <= n && 1 <= y && y <= 2))
return;
if (vis[x][y])
return;
vis[x][y] = 1;
sum++;
if (sum == n * 2) {
++ans;
vis[x][y] = 0;
return;
}
for (int i = -1; i <= 1; ++i)
for (int j = -1; j <= 1; ++j)
if (i != 0 || j != 0) {
dfs(x + i, y + j, ans, sum);
}
vis[x][y] = 0;
}
/*
2 :: 24
3 :: 96
4 :: 416
5 :: 1536
6 :: 5504
7 :: 18944
8 :: 64000
9 :: 212992
10 :: 702464
*/
int main() {
/*
for (n = 2; n <= 10; ++n) {
int ans = 0;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= 2; ++j) {
memset(vis, 0, sizeof(vis));
dfs(i, j, ans, 0);
}
cout << ans << '\n';
}
return 0;
*/
scanf("%lld",&n);
if (n == 1)
puts("2");
else
printf("%d\n",linear_seq::gao(VI{24, 96, 416, 1536, 5504, 18944, 64000, 212992}, n - 2));
return 0;
}
可以推出式子是
∑ i = 0 n C ( n , i ) % 2 \sum_{i = 0}^n C(n, i) \% 2 i=0∑nC(n,i)%2
然后lucas一下,就发现了其实就是2的xxx次方
#include
using namespace std;
using ll = long long;
int main() {
ll n;
cin >> n;
cout << (1ll << (__builtin_popcountll(n))) << '\n';
return 0;
}
二分答案
#include
#include
#include
using namespace std;
using ll = long long;
int const N = 1e5 + 5;
int a[N];
int n, m, K;
bool check(ll lim) {
ll s = 0;
int can = 0;
for (int i = 1; i <= n; ++i) {
if (a[i] > lim * K)
return 0;
if (s + a[i] > lim * K) {
++can;
s = a[i];
} else
s += a[i];
}
if (s)
++can;
return can <= m;
}
int main() {
cin >> n >> m >> K;
for (int i = 1; i <= n; ++i)
cin >> a[i];
int l = 1, r = 1e9, ans = -1;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid)) {
ans = mid;
r = mid - 1;
} else
l = mid + 1;
}
cout << ans << '\n';
}