The Preliminary Contest for ICPC Asia Shenyang 2019
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)!\)种情况。
那么反面情况的总概率为:
\]
之后随便化一化就出来了。
正难则反。
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的更多相关文章
- The Preliminary Contest for ICPC Asia Shenyang 2019 F. Honk's pool
题目链接:https://nanti.jisuanke.com/t/41406 思路:如果k的天数足够大,那么所有水池一定会趋于两种情况: ① 所有水池都是一样的水位,即平均水位 ② 最高水位的水池和 ...
- The Preliminary Contest for ICPC Asia Shenyang 2019 H. Texas hold'em Poker
题目链接:https://nanti.jisuanke.com/t/41408 题目意思很简单,就是个模拟过程. #include <iostream> #include <cstr ...
- 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 ...
- The Preliminary Contest for ICPC Asia Shenyang 2019 H
H. Texas hold'em Poker 思路:根据每个牌型分等级,然后排序按照等级优先,最大值次之,次大值,最后比较剩下值的和. #include<bits/stdc++.h> us ...
- 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]也不需要更新.如果不整取的话,后 ...
- The Preliminary Contest for ICPC Asia Shenyang 2019 D. Fish eating fruit(树形dp)
题意:求一棵树上所有路径和模3分别为0 1 2 的权值的和 思路:树形dp 增加一个记录儿子节点满足条件的个数的数组 不要放在一起dp不然答案跟新会有问题 #include <bits/stdc ...
- 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/ ...
- The Preliminary Contest for ICPC Asia Nanjing 2019/2019南京网络赛——题解
(施工中……已更新DF) 比赛传送门:https://www.jisuanke.com/contest/3004 D. Robots(期望dp) 题意 给一个DAG,保证入度为$0$的点只有$1$,出 ...
- 计蒜客 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 ...
随机推荐
- Spring Boot常用注解和原理整理
一.启动注解 @SpringBootApplication @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documen ...
- 一步一步搭建 Oracle Data Guard
前言 为什么要写前言,因为我要吐槽一下.作为一个Java后端,搭建Oracle Data Guard真的是一件,嗯,既不专业也不擅长的事情,然而,为什么还是要我来弄? 因为DBA出差了,我们这边急着要 ...
- 对python函数后面有多个括号的理解?
一般而言,函数后面只有一个括号.如果看见括号后还有一个括号,说明第一个函数返回了一个函数,如果后面还有括号,说明前面那个也返回了一个函数.以此类推. 比如fun()() def fun(): prin ...
- vue element之axios下载文件(后端Python)
axios 接受文件流,需要设置 {responseType:'arraybuffer'} axios.post( apiUrl, formdata, {responseType:'arraybuff ...
- UML简单介绍—类图这么看就懂了
如何看懂类图 1.类图简介 描述类的内部结构和类与类之间的关系,是一种静态结构图. 在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关 ...
- Django Forms ChoiceField 选项更新问题
今天使用django的forms,发现单选后台新增数据后,前端表单选项不能刷新 class UserForm(forms.Form): name = forms.ChoiceField( choice ...
- 如何用web3部署智能合约
合约示例 pragma solidity ^0.4.18; contract CallMeChallenge { bool public isComplete = false; function ca ...
- 团队项目之Scrum7
小组:BLACK PANDA 时间:2019.11.27 每天举行站立式会议 提供当天站立式会议照片一张 2 昨天已完成的工作 2 内容展示 根据三大板块进行分类: 电影. 音乐以及摄影 今天计划完成 ...
- SQL Server之批量清理数据库的死锁
DECLARE killspid CURSOR FOR (SELECT CONVERT(VARCHAR(100), request_session_id) FROM sys.dm_tran_l ...
- 12.2新特性 使用DBCA duplicate创建物理备用数据库 (Doc ID 2283697.1)
Creating a Physical Standby database using DBCA duplicate (Doc ID 2283697.1) APPLIES TO: Oracle Data ...