博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2017 CCPC Qinhuangdao Site
阅读量:5256 次
发布时间:2019-06-14

本文共 13125 字,大约阅读时间需要 43 分钟。

A. Balloon Robot

假设机器人$0$时刻位于$0$号位置,那么每个气球所需的时间为$(s_a-b)\bmod m$。

将所有气球按这个时间排序,枚举每个气球的时间作为偏移量,得出最优解即可。

时间复杂度$O(p\log p)$。

#include
#include
using namespace std;typedef long long ll;const int N=1000010;int T,n,m,p,i,s[N];ll f[N],init,ans;int main(){ scanf("%d",&T); while(T--){ scanf("%d%d%d",&n,&m,&p); for(i=1;i<=n;i++)scanf("%d",&s[i]); init=0; for(i=1;i<=p;i++){ int a,b; scanf("%d%d",&a,&b); f[i]=((s[a]-b)%m+m)%m; init+=f[i]; } ans=init; sort(f+1,f+p+1); for(i=1;i<=p;i++)ans=min(ans,init-1LL*p*f[i]+1LL*(i-1)*m); printf("%lld\n",ans); }}

  

B. Expected Waiting Time

设$f_n$表示长度为$n$的合法括号序列个数,则奇数为$0$,偶数为卡特兰数。

分母一定是$f_{2n}$,而对于分子,可以考虑每个位置作为左右括号的贡献,假设是第$i$个位置作为左括号,那么枚举与其配对的右括号的距离$j$,则中间的方案数为$f_{j-1}$,剩下部分的方案数为$f_{2n-j-1}$,故总方案数为$\sum_{j=1}^{2n-i}f_{j-1}f_{2n-j-1}$。

注意到$i$只影响上式的求和上界,故直接计算出每个的值即可。

时间复杂度$O(n)$。

#include
typedef long long ll;const int N=5000000;int n,P,b,A,B,T,i,a[N],sum,ans;int h[N],inv[N];inline ll po(ll a,ll b){ ll t=1; for(;b;b>>=1,a=a*a%P)if(b&1)t=t*a%P; return t;}inline int C(int n){ if(n&1)return 0; return h[n>>1];}int main(){ scanf("%d",&T); while(T--){ scanf("%d%d%d%d%d",&n,&P,&b,&A,&B); h[0]=1; h[1]=1; inv[0]=inv[1]=1; for(i=2;i<=n+1;i++)inv[i]=1LL*(P-inv[P%i])*(P/i)%P; for(i=2;i<=n;i++)h[i]=1LL*h[i-1]*(i*4-2)%P*inv[i+1]%P; n*=2; for(i=1;i<=n;i++){ b=(1LL*b*A+B)%P; a[i]=(1LL*a[i-1]+1LL*b+1)%P; } sum=0; ans=0; for(i=1;i

  

C. Crusaders Quest

爆搜所有可行方案即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }#define MS(x, y) memset(x, y, sizeof(x))#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template
inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }template
inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }const int N = 0, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;template
inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }int casenum, casei;char w[4] = "gao";int p[4];int ANS;void dfs(int o, string s, int val){ if(o == 2) { gmax(ANS, val + 1); return; } int len = s.length(); string nxt = ""; for(int j = 0; j < len; ++j)if(s[j] != w[p[o]])nxt = nxt + s[j]; bool flag = 0; for(int i = 0; i < len; ++i)if(s[i] == w[p[o]]) { flag = (s[i] == s[i + 1] && s[i] == s[i + 2]); break; } dfs(o + 1, nxt, val + flag);}int main(){ scanf("%d", &casenum); for (casei = 1; casei <= casenum; ++casei) { string s; cin >> s; for(int i = 0; i < 3; ++i)p[i] = i; ANS = 0; do { dfs(0, s, 0); }while(next_permutation(p, p + 3)); printf("%d\n", ANS); } return 0;}/*【trick&&吐槽】【题意】【分析】【时间复杂度&&优化】*/

  

D. Graph Generator

从后往前还原整个过程。

若图只有一个点,那么方案显然。

若图由多个连通块构成,那么每个连通块之间是独立的,分开处理即可。

否则图只剩下一个大小至少为$2$的连通块,那么最后一步操作必然选择一个到其它每个点都有边的点,然后将图继续分裂成若干连通块。

注意到对于$n$个点的连通块,边数会减少$n-1$,故迭代层数不超过$O(\sqrt{n})$。

时间复杂度$O(n\sqrt{n})$。

#include
#include
#include
using namespace std;typedef pair
P;const int N=100010,M=200010;int Case,n,m,i,qa[N],qb[M],tmp[M];int fin[N];//should reversevector
ans[N];int stage;bool err;struct E{ int x,y;}e[M];int deg[N],g[N],v[M<<1],nxt[M<<1],ed;int vis[N];int cnt;int q[N],cq;int pos[M];inline void add(int x,int y){ v[++ed]=y; nxt[ed]=g[x]; g[x]=ed; deg[x]++;}void dfs(int x){ if(vis[x])return; vis[x]=cnt; q[++cq]=x; for(int i=g[x];i;i=nxt[i])dfs(v[i]);}void solve(int nl,int nr,int ml,int mr,vector
&old){ if(err)return; //for(int i=nl;i<=nr;i++)printf("%d ",qa[i]);puts(""); if(nl==nr){ fin[++stage]=qa[nl]; old.push_back(qa[nl]); return; } //find connect comp int i,j; cnt=ed=0; for(i=nl;i<=nr;i++){ int x=qa[i]; deg[x]=g[x]=vis[x]=0; } for(i=ml;i<=mr;i++)add(e[qb[i]].x,e[qb[i]].y),add(e[qb[i]].y,e[qb[i]].x); cq=0; for(i=nl;i<=nr;i++){ int x=qa[i]; if(!vis[x]){ old.push_back(x); cnt++; dfs(x); } } if(cnt==1){ int cv=nr-nl; for(i=nl;i<=nr;i++)if(deg[qa[i]]==cv)break; if(i>nr){ err=1; return; } int x=qa[i]; swap(qa[nl],qa[i]); int L=ml,R=ml-1; for(i=ml;i<=mr;i++){ int u=e[qb[i]].x,v=e[qb[i]].y; if(u==x||v==x)continue; tmp[++R]=qb[i]; } for(i=L;i<=R;i++)qb[i]=tmp[i]; fin[++stage]=x; solve(nl+1,nr,L,R,ans[stage]); }else{ vector

nson,mson; int l=nl; for(i=1;i<=cq;i=j){ int r=l-1; for(j=i;j<=cq&&vis[q[i]]==vis[q[j]];j++){ qa[++r]=q[j]; } nson.push_back(P(l,r)); l=r+1; } for(i=1;i<=cnt;i++)pos[i]=0; pos[0]=ml-1; for(i=ml;i<=mr;i++)pos[vis[e[qb[i]].x]]++; for(i=1;i<=cnt;i++)pos[i]+=pos[i-1]; for(i=1;i<=cnt;i++)mson.push_back(P(pos[i-1]+1,pos[i])); for(i=ml;i<=mr;i++){ int x=vis[e[qb[i]].x]; tmp[pos[x]--]=qb[i]; } for(i=ml;i<=mr;i++)qb[i]=tmp[i]; int _cnt=cnt; for(i=0;i<_cnt;i++){ ans[0].clear(); solve(nson[i].first,nson[i].second,mson[i].first,mson[i].second,ans[0]); } }}int main(){ scanf("%d",&Case); while(Case--){ scanf("%d%d",&n,&m); for(i=1;i<=n;i++)qa[i]=i; for(i=1;i<=m;i++)qb[i]=i; for(i=1;i<=m;i++)scanf("%d%d",&e[i].x,&e[i].y); stage=err=0; for(i=0;i<=n;i++)ans[i].clear(); solve(1,n,1,m,ans[0]); if(err)puts("No");else{ puts("Yes"); for(i=n;i;i--){ printf("%d %d",fin[i],ans[i].size()); for(int j=0;j

  

E. String of CCPC

设$f[i][j][k]$表示考虑前$i$个字符,目前购买了$j$次,与“CCPC”KMP的指针为$k$的最大净收益。

注意到最优解中$j$为个位数,令其不超过$9$即可。

时间复杂度$O(n)$。

#include
const int N=200010,M=10;int T,n,m,i,j,k,t,ans,b[N],nxt[N],g[M][2],w[M][2];int f[N][M][4];char a[N];inline void up(int&a,int b){a

  

F. Getting Lost

留坑。

 

G. Numbers

在二进制下从高位到低位贪心考虑。

若答案这一位可以为$0$,那么全部填$0$,否则尽量填$1$。

import java.util.*;import javax.swing.text.TabableView;import java.io.*;import java.math.*;public class Main{	static final int N = (int)1e5 + 10;	static Scanner cin = new Scanner(System.in);	static BigInteger v0 = BigInteger.valueOf(0);	static BigInteger v1 = BigInteger.valueOf(1);	static BigInteger v2 = BigInteger.valueOf(2);	static BigInteger b[] = new BigInteger [4000];	public static void main(String args[])	{		b[0] = v1;		for(int i = 1; i < 4000; ++i)b[i] = b[i - 1].multiply(v2);		int casenum = cin.nextInt();		for(int casei = 1; casei <= casenum; ++casei)		{			BigInteger n = cin.nextBigInteger();			BigInteger m = cin.nextBigInteger();			BigInteger top = n.add(m).subtract(v1).divide(m);			int w = 0;			while(b[w].compareTo(top) <= 0)++w;			BigInteger ans = v0;			for(int k = w; k >= 0; --k)			{				if(n.compareTo( b[k].subtract(v1).multiply(m) ) <= 0)				{									}				else				{					BigInteger g = n.divide(b[k]);					if(g.compareTo(m) > 0)g = m;					n = n.subtract(g.multiply(b[k]));					ans = ans.add(b[k]);				}			}			System.out.println(ans);		}	}}

  

H. Prime Set

按奇偶建立二分图匹配模型,先忽略$1$求出最大匹配,再考虑$1$继续求最大匹配,每个匹配都将贡献$2$。

对于剩下的数,再检查能否与已选的数配对,每次配对贡献$1$。

注意特殊处理$1$内部的匹配。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }#define MS(x, y) memset(x, y, sizeof(x))#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template
inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }template
inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }const int N = 3030, M = N * N, Z = 1e9 + 7, inf = 0x3f3f3f3f;//edge_num = ???template
inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }int casenum, casei;bool is_prime[(int)2e6 + 10];int nn, K;int o[N], e[N];int ST, ED, pone;int first[N], id;int w[M], cap[M], nxt[M];void ins(int x, int y, int cap_){ w[++id] = y; cap[id] = cap_; nxt[id] = first[x]; first[x] = id; w[++ id] = x; cap[id] = 0; nxt[id] = first[y]; first[y] = id;}int d[N];bool bfs(){ //MS(d, -1); for(int i = 0; i <= ED; ++i)d[i] = -1; queue
q; q.push(ST); d[ST] = 0; while(! q.empty()){ int x = q.front(); q.pop(); for(int z = first[x]; z; z = nxt[z]) if(cap[z]){ int y = w[z]; if(d[y] == -1){ d[y] = d[x] + 1; q.push(y); if(y == ED) return 1; } } } return 0;}int dfs(int x, int all){ if(x == ED) return all; int use = 0; for(int z = first[x]; z; z = nxt[z] ) if(cap[z]){ int y = w[z]; if(d[y] == d[x] + 1){ int tmp = dfs(y, min(cap[z], all - use)); cap[z] -= tmp; cap[z ^ 1] += tmp; use += tmp; if(use == all) break; } } if(use == 0) d[x] = -1; return use;}int dinic(){ int ret = 0; while(bfs()) ret += dfs(ST, inf); return ret;}void prime_init(){ int top = 2e6; MS(is_prime, 1); is_prime[0] = is_prime[1] = 0; for(int i = 2; i <= top; ++i)if(is_prime[i]) { for(int j = i + i; j <= top; j += i) { is_prime[j] = 0; } }}int main(){ prime_init(); scanf("%d", &casenum); for (casei = 1; casei <= casenum; ++casei) { scanf("%d%d", &nn, &K); int odd = 0; int even = 0; int one = 0; for(int i = 1; i <= nn; ++i) { int x; scanf("%d", &x); if(x == 1)++one; else if(x & 1)o[++odd] = x; else e[++even] = x; }o[0] = 1; pone = 0; ST = odd + even + 1; ED = ST + 1; for(int i = 0; i <= ED; ++i)first[i] = 0; id = 1; for(int i = 0; i <= odd; ++i) { for(int j = 1; j <= even; ++j)if(is_prime[o[i] + e[j]]) { ins(i, odd + j, 1); } } for(int i = 1; i <= odd; ++i)ins(ST, i, 1); for(int i = 1; i <= even; ++i)ins(odd + i, ED, 1); int ORI_ONE = one; int now = dinic(); // //printf("two-two pair = %d\n", now); // while(one) { ins(ST, pone, 1); if(dinic()) { ++now; --one; } else break; } now += one / 2; one %= 2; if(K <= now) { printf("%d\n", K * 2); continue; } //K > now K -= now; int sum = 0; for(int i = (1 - one); i <= odd; ++i)if(i == 0 || cap[first[i]] == 0) { bool flag = 0; for(int j = 1; j <= even; ++j)if(is_prime[o[i] + e[j]]) { // //printf("single odd for even = %d %d\n", o[i], e[j]); // sum += 1; flag = 1; break; } if(!flag && i == 0 && ORI_ONE > 1)sum += 1; } // //for(int i = 1; i <= even; ++i)printf("cap[%d] = %d\n", e[i], cap[first[odd + i]]); // for(int i = 1; i <= even; ++i)if(cap[first[odd + i]] == 1) { int st = ORI_ONE ? 0 : 1; for(int j = st; j <= odd; ++j)if(is_prime[e[i] + o[j]]) { // //printf("single even for one = %d %d\n", e[i], o[j]); // sum += 1; break; } } int ans = now * 2 + min(sum, K); printf("%d\n", ans); } return 0;}/*【trick&&吐槽】【题意】【分析】【时间复杂度&&优化】6 21 1 1 1 2 26 31 1 1 1 2 26 21 1 10 10 10 107 21 1 1 1 1 2 27 31 1 1 1 1 2 27 41 1 1 1 1 2 2*/

  

I. Triangulation

留坑。

 

J. Tree Equation

留坑。

 

K. Diversity and Variance

留坑。

 

L. One-Dimensional Maze

答案为$\min([2,m]中R的个数,[m,n-1]中L的个数)$。

#include
#include
using namespace std;const int N=1000010;int T,n,m,i,A,B;char a[N];int main(){ scanf("%d",&T); while(T--){ scanf("%d%d%s",&n,&m,a+1); A=B=0; for(i=2;i<=m;i++)if(a[i]=='R')A++; for(i=m;i

  

M. Safest Buildings

下一轮安全区的圆心可行范围可以用圆表示,圆交求出概率即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }#define MS(x, y) memset(x, y, sizeof(x))#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template
inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }template
inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }const int N = 0, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;template
inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }int casenum, casei;const double eps = 1e-8, PI = acos(-1.0);struct circle{ long double x, y, r;}p1, p2;long double sqr(long double x){ return x * x;}long double dis(circle a, circle b){ return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}long double solve(circle a, circle b){ long double d = dis(a, b); if(d >= a.r + b.r) return 0; if(d <= fabs(a.r - b.r)){ long double r = min(a.r, b.r); return PI * r * r; } long double ang1 = acos((a.r * a.r + d * d - b.r * b.r) / (2. * a.r * d)) * 2; long double ang2 = acos((b.r * b.r + d * d - a.r * a.r) / (2. * b.r * d)) * 2; double tmp1 = 0.5 * ang1 * a.r * a.r - 0.5 * a.r * a.r * sin(ang1); double tmp2 = 0.5 * ang2 * b.r * b.r - 0.5 * b.r * b.r * sin(ang2); long double ret = tmp1 + tmp2; return ret; }circle a[110];int b[110];double area[110];int sgn(double x){ if(fabs(x) < eps) return 0; return x > 0 ? 1 : -1;}int main(){ double r; int n; scanf("%d", &casenum); for (casei = 1; casei <= casenum; ++casei) { double R; scanf("%d%lf%lf", &n, &R, &r); a[0].x = 0, a[0].y = 0; a[0].r = R- r; double ans = 0; for(int i = 1; i <= n; i ++){ double x, y; scanf("%lf%lf", &x, &y); a[i].x = x; a[i].y = y; a[i].r = r; area[i] = solve(a[0], a[i]); gmax(ans, area[i]); } int num = 0; for(int i = 1; i <= n; i ++){ if(sgn(area[i] - ans) == 0){ b[++ num] = i; } } printf("%d\n", num); for(int i = 1; i < num; i ++) printf("%d ", b[i]); printf("%d\n", b[num]); } return 0;}/*【trick&&吐槽】【题意】【分析】【时间复杂度&&优化】*/

  

转载于:https://www.cnblogs.com/clrs97/p/7824407.html

你可能感兴趣的文章
2019春 软件工程实践 助教总结
查看>>
YUV 格式的视频呈现
查看>>
Android弹出框的学习
查看>>
现代程序设计 作业1
查看>>
在android开发中添加外挂字体
查看>>
Zerver是一个C#开发的Nginx+PHP+Mysql+memcached+redis绿色集成开发环境
查看>>
多线程实现资源共享的问题学习与总结
查看>>
Learning-Python【26】:反射及内置方法
查看>>
torch教程[1]用numpy实现三层全连接神经网络
查看>>
java实现哈弗曼树
查看>>
转:Web 测试的创作与调试技术
查看>>
python学习笔记3-列表
查看>>
程序的静态链接,动态链接和装载 (补充)
查看>>
关于本博客说明
查看>>
线程androidAndroid ConditionVariable的用法
查看>>
转载:ASP.NET Core 在 JSON 文件中配置依赖注入
查看>>
socket初识
查看>>
磁盘测试工具
查看>>
代码变量、函数命名神奇网站
查看>>
redis cli命令
查看>>