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[n]<<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[n].fi<<' '<<-res[n].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[n][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;
}