传送门

B. Dudu's maze

题意:

是什么鬼东西???我读题可以读半小时QAQ

给出一张无向图,一个人在里面收集糖果,每个点都有一个糖果,特殊点除外。当他第一次进入特殊点时,会随机往一条边走;之后再进入特殊点时,直接退出。

问最后期望获得的糖果数为多少。

思路:

  • 注意到这个人肯定会贪心走的,即是每次到一个连通块,肯定要把里面的糖果都拿完,然后再选一个随机走。
  • 不管往哪个方向,还是类似地贪心走,将那个连通块走完。
  • 所以就两次\(dfs\)好了,第一次\(dfs\)首先求出第一个连通块,然后标出所有的特殊点;第二次\(dfs\)以特殊点为起点搜连通块。

大体思路就是这样,注意一些细节:就是可能以某个特殊点为起点的时候,会多次到达同一个连通块,但答案不能重复计算。这里我的解决办法就是用了一个类似于时间戳一样的东西来进行标记,同一个连通块的属于同一个时间,并且用一个数组记录时间的答案。

详见代码:

Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005, M = 200005; int n, m, k;
int T;
bool chk[N]; struct Edge{
int v, next;
}e[M << 1];
int head[N], tot;
void adde(int u, int v) {
e[tot].v = v; e[tot].next = head[u]; head[u] = tot++;
} bool vis[N];
vector <int> vec;
int dfs(int u) {
int sz = 1; vis[u] = 1;
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if(vis[v] || chk[v]) {
if(chk[v]) vec.push_back(v);
continue;
}
sz += dfs(v);
}
return sz;
} int dfn;
int D[N], ans[N], du[N];
int dfs2(int u) {
int sz = (chk[u] ? 0 : 1);
D[u] = dfn; vis[u] = 1;
for(int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if(chk[v]) continue;
if(vis[v]) {
if(chk[u] && !chk[v]) sz += ans[D[v]];
continue;
}
if(chk[u]) {
ans[++dfn] = dfs2(v);
sz += ans[dfn];
}
else sz += dfs2(v);
}
return sz;
} int main() {
// freopen("input.in", "r", stdin);
cin >> T;
while(T--) {
cin >> n >> m >> k;
for(int i = 0; i <= n; i++) {
du[i] = ans[i] = D[i] = 0;
head[i] = -1; chk[i] = vis[i] = false;
}
vec.clear();
tot = 0;
for(int i = 1; i <= m; i++) {
int u, v; scanf("%d%d", &u, &v);
adde(u, v); adde(v, u);
++du[u], ++du[v];
}
for(int i = 1; i <= k; i++) {
int x; scanf("%d", &x);
chk[x] = true;
}
int res = dfs(1), tmp;
double ANS = 0;
dfn = 0;
for(auto it : vec) {
int sz = dfs2(it);
ANS = max(ANS, res + 1.0 * sz / du[it]);
}
printf("%.8f\n", ANS);
}
return 0;
}

C. Dawn-K's water

简单\(dp\)。

Code
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 1e4+5,MAXM = 2e6+5,MOD = 998244353,INF = 0x3f3f3f3f;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-9;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
using namespace std; int n,m,p[1005],c[1005];
ll f[10005];
int main(){
ios::sync_with_stdio(false);
//freopen("../A.in","r",stdin);
//freopen("../A.out","w",stdout);
while(cin>>n>>m){
ll ans=1000000000000000;
int b=-1,up=10000,sum=0;
for(int i=1;i<=n;i++){
cin>>p[i]>>c[i];
sum+=c[i];
}
//up=min(up,sum);
f[0]=0;
for(int i=1;i<=up;i++)f[i]=1000000000000000;
for(int i=1;i<=n;i++){
for(int j=c[i];j<=up;j++){
f[j] = min(f[j],f[j-c[i]] + p[i]);
}
}
for(int i=m;i<=up;i++){
if(f[i]<=ans){
ans=f[i];
b=i;
}
}
//assert(ans>=1&&ans<=1000000000);
assert(b!=-1);
cout<<ans<<' '<<b<<'\n';
}
return 0;
}

D. Fish eating fruit

题意:

这什么题意啊,欺负我英语不好么QAQ

思路:

按照模\(3\)余数分类,然后换根\(dp\)就行了。

代码队友写的,可能有点迷(我反正没怎么看懂)

Code
#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int MAXN = 1e4+5,MAXM = 2e4+5,MOD = 1e9+7,INF = 0x3f3f3f3f;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
const db eps = 1e-9;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define pii pair<int,int>
#define vii vector<pii>
#define vi vector<int>
using namespace std;
struct Edge{
int v,w,next;
}e[MAXM];
int n,a,b,c,head[MAXN],cnt,f1[MAXN][3],g1[MAXN][3],ans[3],f2[MAXN][3],g2[MAXN][3];
inline void init(){
cnt=0;
for(int i=1;i<=n;i++)head[i]=0;
for(int i=1;i<=n;i++){
for(int r=0;r<3;r++)f1[i][r]=g1[i][r]=0;
}
}
inline void addEdge(int u,int v,int w){
e[++cnt] = {v,w,head[u]};head[u]=cnt;
}
inline void add(int &x,int y){
x+=y;
if(x>=MOD)x-=MOD;
}
void dfs(int u,int p){
g1[u][0]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(v==p)continue;
dfs(v,u);
for(int r=0;r<3;r++){
add(f1[u][(e[i].w+r)%3],(f1[v][r] + (ll)g1[v][r]*e[i].w%MOD)%MOD);
add(g1[u][(e[i].w+r)%3],g1[v][r]);
}
}
}
void solve(int u,int p){
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(v==p)continue;
for(int r=0;r<3;r++){
int t = (r+e[i].w)%3;
int t2 = ((r-e[i].w)%3+3)%3;
add(f2[v][t],(f2[u][r]-f1[v][t2]-(ll)g1[v][t2]*e[i].w + (ll)e[i].w*(g2[u][r] - g1[v][t2])%MOD+MOD)%MOD);
add(g2[v][t],(g2[u][r]-g1[v][t2]+MOD)%MOD);
}
solve(v,u);
}
}
int main(){
ios::sync_with_stdio(false);
//freopen("../A.in","r",stdin);
//freopen("../A.out","w",stdout);
while(cin>>n){
init();
for(int i=1;i<n;i++){
cin>>a>>b>>c;
a++;b++;
addEdge(a,b,c);addEdge(b,a,c);
}
dfs(1,0);
for(int i=1;i<=n;i++){
for(int r=0;r<=2;r++){
g2[i][r] =g1[i][r];
f2[i][r] =f1[i][r];
}
}
solve(1,0);
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++){
for(int r=0;r<3;r++)add(ans[r],f2[i][r]);
}
cout<<ans[0]<<' '<<ans[1]<<' '<<ans[2]<<'\n';
}
return 0;
}

F. Honk's pool

考虑先取最大的数,可以二分一个最后的最大值,然后随便搞搞,把取完过后的数组求出来。

之后贪心依次来放就行。

总的来说,就是将取和放独立开,这两个是独立的,并不影响。

为什么?

我也不会证= =。

Code
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll; const int N = 500005; ll k, n;
ll a[N], sum[N]; bool chk(int x) {
int p = lower_bound(a + 1, a + n + 1, x) - a;
int num = n - p + 1;
ll S = sum[p] - 1ll * x * num;
return S <= k;
} int main() {
ios::sync_with_stdio(false); cin.tie(0);
while(cin >> n >> k) {
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1); sum[n + 1] = 0;
for(int i = n; i >= 1; i--) sum[i] = sum[i + 1] + a[i];
int l = 0, r = INF, mid;
while(l < r) {
mid = (l + r) >> 1;
if(chk(mid)) r = mid;
else l = mid + 1;
}
int v = r;
int p = lower_bound(a + 1, a + n + 1, v) - a;
int num = n - p + 1;
ll S = sum[p] - 1ll * v * num;
k -= S;
for(int i = p; i <= n; i++) a[i] = v;
for(int i = p; i <= min(n, p + k - 1); i++) {
if(a[i]) { --a[i]; ++S; }
}
// for(int i = 1; i <= n; i++) cout << a[i] << ' ';
// cout << '\n';
int cnt = 1, f = 1;
for(int i = 1; i <= n; i++) {
if(a[i] >= v) break;
ll tmp = 1ll * cnt * (a[i + 1] - a[i]);
if(S <= tmp) {
int now = S / cnt;
cout << v - (a[i] + now) << '\n';
f = 0; break;
}
S -= 1ll * cnt * (a[i + 1] - a[i]);
++cnt;
}
if(f == 0) continue;
if(S % n) cout << 1 << '\n';
else cout << 0 << '\n';
}
return 0;
}
/*
3 10000000
1 2 3
*/

H. Texas hold'em Poker

题意:

不懂。

思路:

模拟。

Code
#include<cstdio>
#include<cmath>
#include<cctype>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
#define REP(r,x,y) for(register int r=(x); r<y; r++)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__)
#else
#define DBG(...) (void)0
#endif
template <class T>
inline void read(T&x) {
static int si=1; static char ch; x=0;
do ch=getchar(); while(!isdigit(ch) && ch!='-');
if(ch=='-') si=-1, ch=getchar();
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} x*=si;
}
template <class T, class... A> inline void read(T&t, A&...a){read(t); read(a...);}
#define MAXN 100007
char nm[MAXN][17];
struct node {
int id;
int s[5];
int kind;
int v,v2,v3;
};
node p[MAXN];
inline void readpai(int x) {
char ch;
REP(i,0,5) {
do ch=getchar(); while(ch<=' ');
#define L p[x].s[i]
switch(ch) {
case 'A':
L=1; break;
case '1':
getchar();
L=10; break;
case 'J':
L=11; break;
case 'Q':
L=12; break;
case 'K':
L=13; break;
default:
L=ch-'0'; break;
}
#undef L
}
sort(p[x].s,p[x].s+5);
}
inline void processpai(int x) {
const int *X=p[x].s; int &K=p[x].kind, &V=p[x].v, &V2=p[x].v2, &V3=p[x].v3;
//7 XJQKA
const int RS[]={1,10,11,12,13};
if(memcmp(X,RS,sizeof RS)==0) {K=7;V=0;return;}
//6 12345
if(X[1]-X[0]==1 && X[2]-X[1]==1 && X[3]-X[2]==1 && X[4]-X[3]==1) {K=6, V=X[4]; return;}
//5 AAAA
if(X[1]==X[2] && X[2]==X[3]) {
if(X[0]==X[1]) {K=5, V=X[1], V2=X[4]; return;}
if(X[3]==X[4]) {K=5, V=X[1], V2=X[0]; return;}
}
//4 AAABB
if(X[0]==X[1] && X[1]==X[2] && X[3]==X[4]) {K=4, V=X[0], V2=X[3]; return;}
if(X[0]==X[1] && X[2]==X[3] && X[3]==X[4]) {K=4, V=X[2], V2=X[0]; return;}
//3 AAABC
if(X[0]==X[1] && X[1]==X[2]) {K=3, V=X[0], V2=X[3]+X[4]; return;}
if(X[1]==X[2] && X[2]==X[3]) {K=3, V=X[1], V2=X[0]+X[4]; return;}
if(X[2]==X[3] && X[3]==X[4]) {K=3, V=X[2], V2=X[0]+X[1]; return;}
//2 AABBC
if(X[0]==X[1] && X[2]==X[3]) {K=2, V=X[2], V2=X[0], V3=X[4]; return;}
if(X[0]==X[1] && X[3]==X[4]) {K=2, V=X[3], V2=X[0], V3=X[2]; return;}
if(X[1]==X[2] && X[3]==X[4]) {K=2, V=X[3], V2=X[1], V3=X[0]; return;}
//1 AABCD
if(X[0]==X[1]) {K=1, V=X[0], V2=X[2]+X[3]+X[4]; return;}
if(X[1]==X[2]) {K=1, V=X[1], V2=X[0]+X[3]+X[4]; return;}
if(X[2]==X[3]) {K=1, V=X[2], V2=X[0]+X[1]+X[4]; return;}
if(X[3]==X[4]) {K=1, V=X[3], V2=X[0]+X[1]+X[2]; return;}
//0
{K=0, V=X[0]+X[1]+X[2]+X[3]+X[4];return;}
}
bool nmcmp(const node&l, const node&r) {
return strcmp(nm[l.id],nm[r.id])<0;
}
bool cmp(const node&l, const node&r) {
const bool T=false;
if(l.kind<r.kind) return T;
if(l.kind==r.kind) {
switch(l.kind) {
case 0:
case 6:
case 7:
if(l.v<r.v) return T;
if(l.v==r.v) return nmcmp(l,r);
else return !T;
case 1:
case 3:
case 4:
case 5:
if(l.v<r.v) return T;
if(l.v==r.v) {
if(l.v2<r.v2) return T;
if(l.v2==r.v2) {
return nmcmp(l,r);
} else return !T;
} else return !T;
case 2:
if(l.v<r.v) return T;
if(l.v==r.v) {
if(l.v2<r.v2) return T;
if(l.v2==r.v2) {
if(l.v3<r.v3) return T;
if(l.v3==r.v3) {
return nmcmp(l,r);
} else return !T;
} else return !T;
} else return !T;
}
}
return !T; }
int main() {
int n;
while(~scanf("%d", &n)) {
REP(i,0,n) {
scanf("%s", nm[i]);
p[i].id=i;
readpai(i);
processpai(i);
}
sort(p,p+n,cmp);
REP(i,0,n) {
puts(nm[p[i].id]);
}
}
return 0;
}

J. Ghh Matin

题意:

给出\(n\)个点,现在随机生成边,要求每个点只有一条出边和一条入边(形成若干个环)。同时给出一个\(x\)。

问最后生成的最长环不超过\(x\)的概率。

注意\(2x\geq n\)。

思路:

首先可以知道,对于\(n\)个点,随机形成若干个环的情况总数为\(n!\)。为什么?

因为最后的图中肯定有\(n\)条边,我们现在开始一条一条加边,第一次选择两个出度为\(0\)和入度为\(0\)的点将其相连,易知一开始有\(n\)总选择,后面依次有\(n-1,n-2,\cdots,1\)种选择。

注意条件\(2x\geq n\),那么说明图中长度大于\(x\)的环最多只有一个,那么我们考虑反面,就枚举所有不合法的情况,此时就很好计算:

假设现在考虑长度为\(m\)的环,那么首先会从\(n\)个里面选择\(m\)个,之后会随机成环,此时只有\((m-1)!\)种情况,相当于固定一个点,其它点随机排列(如果直接全排列,可能会有重复的)。之后剩下的点随机成环,有\((n-m)!\)种情况。

那么反面情况的总概率为:

\[\sum_{m=x+1}^n{n\choose m}(m-1)!(n-m)!/n!
\]

之后随便化一化就出来了。

正难则反。

Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
//#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e6 + 5, MOD = 1e9 + 7; int n, x;
int p[N]; ll qpow(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ans;
} void init() {
for(int i = 1; i < N; i++) p[i] = qpow(i, MOD - 2);
} void run() {
cin >> n >> x;
int ans = 0;
for(int i = x + 1; i <= n; i++) ans = (ans + p[i]) % MOD;
ans = (1 - ans + MOD) % MOD;
cout << ans << '\n';
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
#ifdef Local
freopen("../input.in", "r", stdin);
freopen("../output.out", "w", stdout);
#endif
init();
int T; cin >> T;
while(T--) run();
return 0;
}

The Preliminary Contest for ICPC Asia Shenyang 2019的更多相关文章

  1. The Preliminary Contest for ICPC Asia Shenyang 2019 F. Honk's pool

    题目链接:https://nanti.jisuanke.com/t/41406 思路:如果k的天数足够大,那么所有水池一定会趋于两种情况: ① 所有水池都是一样的水位,即平均水位 ② 最高水位的水池和 ...

  2. The Preliminary Contest for ICPC Asia Shenyang 2019 H. Texas hold'em Poker

    题目链接:https://nanti.jisuanke.com/t/41408 题目意思很简单,就是个模拟过程. #include <iostream> #include <cstr ...

  3. The Preliminary Contest for ICPC Asia Shenyang 2019 C. Dawn-K's water

    题目:https://nanti.jisuanke.com/t/41401思路:完全背包 #include<bits/stdc++.h> using namespace std; int ...

  4. The Preliminary Contest for ICPC Asia Shenyang 2019 H

    H. Texas hold'em Poker 思路:根据每个牌型分等级,然后排序按照等级优先,最大值次之,次大值,最后比较剩下值的和. #include<bits/stdc++.h> us ...

  5. The Preliminary Contest for ICPC Asia Shenyang 2019 C Dawn-K's water (完全背包)

    完全背包为什么要取到M,可以取到2*M嘛,这题需要整取,对于不能整取的背包容量,dp[k]=INF,以及dp[j-water[i].weight]=INF时,dp[j]也不需要更新.如果不整取的话,后 ...

  6. The Preliminary Contest for ICPC Asia Shenyang 2019 D. Fish eating fruit(树形dp)

    题意:求一棵树上所有路径和模3分别为0 1 2 的权值的和 思路:树形dp 增加一个记录儿子节点满足条件的个数的数组 不要放在一起dp不然答案跟新会有问题 #include <bits/stdc ...

  7. The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力)

    The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力) 传送门:https://nanti.jisuanke.com/ ...

  8. The Preliminary Contest for ICPC Asia Nanjing 2019/2019南京网络赛——题解

    (施工中……已更新DF) 比赛传送门:https://www.jisuanke.com/contest/3004 D. Robots(期望dp) 题意 给一个DAG,保证入度为$0$的点只有$1$,出 ...

  9. 计蒜客 41391.query-二维偏序+树状数组(预处理出来满足情况的gcd) (The Preliminary Contest for ICPC Asia Xuzhou 2019 I.) 2019年徐州网络赛)

    query Given a permutation pp of length nn, you are asked to answer mm queries, each query can be rep ...

随机推荐

  1. NET Framework项目移植到NET Core上踩的坑(1)

    本文章向大家介绍NET Framework项目移植到NET Core上遇到的一系列坑,主要包括NET Framework项目移植到NET Core上遇到的一系列坑使用实例.应用技巧.基本知识点总结和需 ...

  2. Add the Scheduler Module 添加计划程序模块

    Important 重要 Scheduler requires the Event business class to be in your XAF application model. Follow ...

  3. python3 tornado api + angular8 + nginx 跨域问题

    问题: 上一个博客部署好了api之后,前端开始吊发现了跨域的问题. 接口地址: http://111.231.201.164/api/houses  服务器上使用的是nginx转发 数据: 前端ang ...

  4. 12-Factor与微服务

           为了构建分布式微服务程序,能够部署到所有云服务,Heroku工程师总结所有云原生应用程序的12要素: 1.基准代码 Single codebase: The application mu ...

  5. 追踪SQL Server执行delete操作时候不同锁申请与释放的过程

    一直以为很了解sqlserver的加锁过程,在分析一些特殊情况下的死锁之后,尤其是并发单表操作发生的死锁,对于加解锁的过程,有了一些重新的认识,之前的知识还是有一些盲区在里面的.delete加锁与解锁 ...

  6. centos安装Redis和设置远程访问

    记录下步骤以后用到时翻一翻. 一.下载官方的文件包和编译 在centos下载依赖库: yum install gcc tcl 在redis官网的下载页面,这里可以选择离线包或在线下载. 我选择在线的, ...

  7. Anaconda创建环境失败,提示无法定位程序输入点

    https://blog.csdn.net/qq_37465638/article/details/100071259 这篇博客写得很清楚,是anaconda下Library下lib下的一个文件和DD ...

  8. 基于docker-compose搭建本地sentry服务

    环境要求: centos 7 Docker 17.05.0+ Compose 1.19.0+ RAM 2400MB docker-compose 安装 ``$ curl -L https://get. ...

  9. vue-cli2和cli3的使用和区别

    vue-cli脚手架的使用 使用vue-cli可以快速搭建vue的开发环境,和webpack的配置 安装vue脚手架: npm install -g@vue/cli 上面安装的是vue cli3的版本 ...

  10. 【朝花夕拾】Android自定义View篇之(二)Canvas常用功能

    前言 转在请申明,转自[https://www.cnblogs.com/andy-songwei/p/10960012.html],谢谢! 上一篇讲View的绘制流程中讲到过,最后一步是draw流程, ...