2016"百度之星" - 复赛(Astar Round3) 题解 (待续)
2016-05-29 23:41
513 查看
D++游戏
众所周知,度度熊喜欢的字符只有两个:B 和D。今天,它发明了一个游戏:D游戏。
度度熊的英文并不是很高明,所以这里的D,没什么高深的含义,只是代指等差数列(等差数列百科)中的公差D。
这个游戏是这样的,首先度度熊拥有一个公差集合{D},然后它依次写下N个数字排成一行。游戏规则很简单:
1.在当前剩下的有序数组中选择X(X≥2) 个连续数字;
2.检查1 选择的X个数字是否构成等差数列,且公差 d∈{D};
3.如果2满足,可以在数组中删除这X个数字;
4.重复 1−3 步,直到无法删除更多数字。
度度熊最多能删掉多少个数字,如果它足够聪明的话?
为了挑战自己,度度熊给D游戏多设了一个条件,Xmin和Xmax,在游戏的第一步,选出X个连续数字时,必须满足Xmin≤X≤Xmax。它称这个游戏为D++游戏。
同时精益求精的度度熊还希望知道删掉最多数字的最少步数。
1<=N,M<=32,1<=Xmin,Xmax<=16
考虑dp[k][i][j]为区间[i,j]上取完,且最后一次(取了头,若长度大于1则也取了尾)取了长度为k的等差数列的最小步数
ansi,j为满足Xmin,Xmax约束时,区间[i,j]上取完的最小步数
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<cctype> #include<ctime> #include<iomanip> #include<vector> #include<string> #include<set> #include<queue> #include<stack> #include<map> #include<sstream> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,63,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (1000007) #define pb push_back #define mp make_pair #define fi first #define se second #define vi vector<int> #define pi pair<int,int> #define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans); #define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a <<endl; #define PRi2D(a,n,m) For(i,n) { \ For(j,m-1) cout<<a[i][j]<<' ';\ cout<<a[i][m]<<endl; \ } typedef long long ll; ll mul(ll a,ll b){return (a*b)%F;} ll add(ll a,ll b){return (a+b)%F;} ll sub(ll a,ll b){return ((a-b)%F+F)%F;} void upd(ll &a,ll b){a=(a%F+b%F)%F;} int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN (33) int n,m,L,R; int a[MAXN],dp[MAXN][MAXN][MAXN],ans[MAXN][MAXN]; set<int> d; bool ok[MAXN][MAXN]; pi res[MAXN]; int main() { // freopen("A.in","r",stdin); // freopen(".out","w",stdout); int T=read(); For(kcase,T) { printf("Case #%d:\n",kcase); n=read(); m=read(); L=read(); R=read(); For(i,n) a[i]=read(); d.clear(); For(i,m) d.insert(read()); For(i,n) Fork(j,i+1,n) ok[i][j]=!!d.count(a[j]-a[i]); MEMI(ans) MEMI(dp) For(len,n) For(i,n-len+1) { int j=i+len-1; For(k,R) { if (k>j-i+1) continue; if (i==j) dp[k][i][j]=1; else if (k==1) dp[k][i][j]=1+ans[i+1][j]; else { if ((a[j]-a[i])%(k-1)) continue; int d=(a[j]-a[i])/(k-1); Fork(l,i+1,j) if (ok[i][l]&&a[l]-a[i]==d) { dp[k][i][j]=min(dp[k][i][j], (i+1<=l-1)*ans[i+1][l-1] + dp[k-1][l][j] ); } } } ans[i][j]=dp[L][i][j]; Fork(k,L,R) ans[i][j]=min(ans[i][j], dp[k][i][j]); Fork(l,i,j-1) ans[i][j]=min(ans[i][j], ans[i][l] + ans[l+1][j] ); } res[0]=mp(0,0); For(i,n) { res[i]=res[i-1]; Rep(j,i-1) if (ans[j+1][i]<=n) res[i] = max(res[i],mp(res[j].fi+i-j,res[j].se-ans[j+1][i])); } cout<<res .fi<<' '<<-res .se<<endl; } return 0; }
K个联通块
众所周知,度度熊喜欢图,尤其是联通的图。今天,它在图上又玩出了新花样,新高度。有一张无重边的无向图, 求有多少个边集,使得删掉边集里的边后,图里恰好有KKK个连通块。
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<vector> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=Pre[x];p;p=Next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (1000000009) #define pb push_back #define mp make_pair #define fi first #define se second #define vi vector<int> #define pi pair<int,int> #define SI(a) ((a).size()) typedef long long ll; typedef unsigned long long ull; int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } int n,m,k; int lowbit(int x) { return x&(-x); } int f[1<<14],g[1<<14],h[1<<14],t[1<<14][14]; int ff[15][15]; #define MAXN (14+10) #define MAXM (10+1) int p2[100100]; void prework(int n) { p2[0]=1; For(i,n) p2[i]=(p2[i-1]<<1ll)%F; } int main() { // freopen("B.in","r",stdin); // freopen(".out","w",stdout); int tt; cin>>tt; prework(100000); For(kcase,tt){ printf("Case #%d:\n",kcase); scanf("%d%d%d",&n,&m,&k); MEM(ff) MEM(g) MEM(f) MEM(h) Rep(i,1<<n) h[i]=0; int a,b; For(i,m) { a=read(),b=read();--a;--b; ff[a][b]=ff[b][a]=1; } int tot=1<<n; Rep(S,tot) { Rep(i,n) if (S&(1<<i)) { Fork(j,i,n-1) { if (S&(1<<j)) if (ff[i][j]) h[S]++; } } } Rep(S,tot) h[S]=p2[h[S]]; Rep(i,n) f[1<<i]=1,g[1<<i]=0; Rep(S,tot) { int Q=lowbit(S); for (int x = S-Q; x; x = (x-1)&(S-Q)) { if (!(S-x)) continue; g[S]+=1LL*f[S-x]*h[x]%F; g[S]%=F; } f[S]=h[S]-g[S]; f[S]%=F; if (f[S]<0) f[S]+=F; t[S][1]=f[S]; } Fork(j,2,k) { Rep(S,tot) { t[S][j]=0; int Q=lowbit(S); for (int x = S-Q; x; x = (x-1)&(S-Q)) { t[S][j]=(t[S][j]+1LL*t[x][j-1]*f[S-x]%F)%F; } } } ll ans=t[tot-1][k]%F; printf("%d\n",(int)ans); } return 0; }
拍照
扫描线 模版题#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<vector> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=Pre[x];p;p=Next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define pb push_back #define mp make_pair #define fi first #define se second #define vi vector<int> #define pi pair<int,int> #define SI(a) ((a).size()) typedef long long ll; typedef unsigned long long ull; int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN (10000+10) struct comm{ int x,y,z,d; }ask[MAXN]; struct comm2 { int x,c; comm2(int _x=0,int _c=0){ x=_x,c=_c; } friend bool operator<(comm2 a,comm2 b) { if (a.x!=b.x) return a.x<b.x; return a.c>b.c; } }went[MAXN*2],not_mov[MAXN*2]; int n,sz1,sz2; vector<pi> v; int main() { // freopen("C.in","r",stdin); // freopen(".out","w",stdout); int T; cin>>T; For(kcase,T){ v.erase(v.begin(),v.end()); printf("Case #%d:\n",kcase); n=read(); sz1=sz2=0; For(i,n) { ask[i].x=read(),ask[i].y=read(),ask[i].z=read(),ask[i].d=read(); if (ask[i].y-ask[i].x<=2*ask[i].z) { if (ask[i].d==-1) { went[++sz1]=comm2(ask[i].y-ask[i].z,1); went[++sz1]=comm2(ask[i].x+ask[i].z,-1); } else { not_mov[++sz2]=comm2(ask[i].y-ask[i].z,1); not_mov[++sz2]=comm2(ask[i].x+ask[i].z,-1); } } } sort(went+1,went+1+sz1); sort(not_mov+1,not_mov+1+sz2); int nowc=0; For(i,sz1) { if (went[i].c==1) nowc++; else { v.pb(mp(went[i].x,nowc)); nowc--; } } v.pb(mp(INF,0)); int sz=v.size(); RepD(i,sz-2) v[i].se=max(v[i].se,v[i+1].se); int ans=0; nowc=0; For(i,sz2) { if (not_mov[i].c==1) nowc++; int p=lower_bound(v.begin(),v.end(),mp(not_mov[i].x,0))->se; ans=max(ans,nowc+p); if (not_mov[i].c==-1) nowc--; } cout<<ans<<endl; } return 0; }
XOR 游戏
用字典树查找集合中Xor S最大的值好几次遇到了
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<vector> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=Pre[x];p;p=Next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define pb push_back #define mp make_pair #define fi first #define se second #define vi vector<int> #define pi pair<int,int> #define SI(a) ((a).size()) typedef long long ll; typedef unsigned long long ull; int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXNode 400000 #define Sigma_size 2 class Trie { public: int ch[MAXNode][Sigma_size]; int v[MAXNode],siz; Trie(int _siz=0):siz(_siz){MEM(ch) MEM(v)} void mem(int _siz=0){siz=_siz; MEM(ch) MEM(v) } int idx(char c){return c-'a';} void insert(int X,int val=0) { int u=0; for(int i=(1<<30);i;i>>=1) { int c=(X&i)>0; if (!ch[u][c]) { ++siz; MEM(ch[siz]); ch[u][c]=siz; } u=ch[u][c]; v[u]+=val; } } int find(int X) { int u=0,res=0; for(int i=(1<<30);i;i>>=1) { int c=(X&i)>0; if (v[ch[u][c^1]]) { u=ch[u][c^1]; res+=i; } else if (v[ch[u][c]]) { u=ch[u][c]; } else return 0; } return res; } }T; #define MAXN (10000+10) #define MAXM (10+1) int n,m,L; ll f[MAXN][MAXM],a[MAXN],S[MAXN]; ll check(ll mid) { MEM(f) For(i,L) if (S[i]>=mid) f[i][1]=1; Fork(j,2,m) { For(i,j-1) { if (f[i][j-1]) T.insert(S[i],1); } Fork(i,j,n) { if (T.find(S[i])>=mid) f[i][j]=1; if (i-L>0&&f[i-L][j-1]) T.insert(S[i-L],-1); if (f[i][j-1]) T.insert(S[i],1); } Fork(i,n-L+1,n) { if (f[i][j-1]) T.insert(S[i],-1); } } return f [m]; } int main() { // freopen("D.in","r",stdin); // freopen(".out","w",stdout); int tt; T.mem(); cin>>tt;S[0]=0; For(kcase,tt){ printf("Case #%d:\n",kcase); cin>>n>>m>>L; For(i,n) { scanf("%I64d",&a[i]); S[i]=S[i-1]^a[i]; } ll L=0,R=1<<30,ans=0; while(L<=R) { ll m=(L+R)/2; if (check(m)) L=m+1,ans=m; else R=m-1; } cout<<ans<<endl; } return 0; }
带可选字符的多字符串匹配
裸的shift-and算法#include<iostream> #include<cstring> #include<cstdlib> #include<cctype> #include<bitset> #include<cstdio> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=Pre[x];p;p=Next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) #define Lson (o<<1) #define Rson ((o<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define pb push_back #define mp make_pair #define fi first #define se second #define vi vector<int> #define pi pair<int,int> #define SI(a) ((a).size()) int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } int id(char c) { if (isupper(c)) return c-'A'; else if (islower(c)) return c-'a'+26; else if (isdigit(c)) return c-'0'+26+26; return 64; } #define MAXN (2000012) #define MAXM (500+10) #define Sigma_size (65) class shift_and{ public: int n,r; bitset<MAXM> v,f[Sigma_size]; int s[MAXN]; void prework() { //s s2 n r } bool b[MAXN]; void work() { Rep(i,Sigma_size) f[i].reset(); MEM(b) char str[100]; Rep(i,r) { int k;scanf("%d",&k); scanf("%s",str); Rep(j,k) f[id(str[j])][i+1]=1; } v.reset();v[0]=1; Rep(i,n) { if (s[i]!=64) v=v<<1&f[s[i]]; else v=0; v[0]=1; b[i]=v[r]; } } }S; char s[MAXN]; int main() { // freopen("hdu5716.in","r",stdin); while(gets(s)) { S.n=strlen(s); scanf("%d",&S.r); Rep(i,S.n) S.s[i]=id(s[i]); S.work(); bool fl=0; Fork(i,S.r-1,S.n-1) if (S.b[i]) fl=1,printf("%d\n",i-S.r+2); if (!fl) puts("NULL"); getchar(); } return 0; }
相关文章推荐
- MySQL分组查询Group By实现原理详解
- 2016第22周日
- hadoop参数配置
- Android 通用流行框架大全
- C#-DataTable分页代码
- #java读书笔记#IO流2
- 常见算法小测试
- git 配置用户名和邮箱
- Shell语法速查
- 由浅入深探究 MySQL索引结构原理、性能分析与优化(强烈推荐)
- Java应用--显示数据库中的信息
- STM32F0xx_TIM基本延时配置详细过程
- 练习三1024
- Java基础回顾 : 利用字节流实现文件的拷贝
- HDOJ 5365 Run
- 鼠标设置按键功能方式(例如设置鼠标侧键为复制粘贴功能)
- ubuntu 安装 单机版hbase
- Android_ListView_BaseAdapter
- 第四章 android 命名规范和编码规范
- 二叉树中的那些常见的题