BestCoder Round #77
计算组合数然后多重集排列乱搞,注意判无解情况(TM我就判错然后FST了)。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } typedef long long ll; const int maxn=1010; const int mod=1000000007; int n,c[26]; char s[maxn]; ll C[maxn][maxn]; void solve() { memset(c,0,sizeof(c)); scanf("%s",s+1);n=strlen(s+1); rep(i,1,n) c[s[i]-'a']++; int sum=0; rep(i,0,25) { if(c[i]&1) sum++,c[i]--; c[i]>>=1; } if(sum>1) {puts("0");return;} ll ans=1;int cur=0; rep(i,0,25) { cur+=c[i]; (ans*=C[cur][c[i]])%=mod; } printf("%I64d\n",ans); } int main() { C[0][0]=1; rep(i,1,1000) { C[i][0]=C[i][i]=1; rep(j,1,i-1) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } dwn(T,read(),1) solve(); return 0; }
转化成对偶图然后统计八连块联通性。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } typedef long long ll; const int mx[]={0,0,1,-1,1,-1,1,-1}; const int my[]={1,-1,0,0,1,1,-1,-1}; const int maxn=510; int pa[maxn*maxn],n,m; int id(int i,int j) {return (i-1)*m+j;} char s[maxn]; int findset(int x) {return pa[x]==x?x:pa[x]=findset(pa[x]);} void Add(int x,int y) { pa[id(x,y)]=id(x,y); rep(dir,0,7) { int nx=x+mx[dir],ny=y+my[dir]; if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&pa[id(nx,ny)]) pa[findset(id(nx,ny))]=findset(id(x,y)); } } void solve() { n=read();m=read();int S=n*m+1,T=n*m+2; memset(pa,0,sizeof(pa));pa[S]=S;pa[T]=T; rep(i,1,n) { scanf("%s",s+1); rep(j,1,m) { if(s[j]=='1') Add(i,j); if(j==1&&s[j]=='1') pa[findset(S)]=findset(id(i,j)); if(j==m&&s[j]=='1') pa[findset(T)]=findset(id(i,j)); } } int k=read(),ok=0; if(findset(S)==findset(T)) {puts("0");ok=1;} rep(i,1,k) { int x=read()+1,y=read()+1; Add(x,y); if(y==1) pa[findset(S)]=findset(id(x,y)); if(y==m) pa[findset(T)]=findset(id(x,y)); if(!ok&&findset(S)==findset(T)) {printf("%d\n",i);ok=1;} } if(!ok) printf("-1\n"); } int main() { dwn(T,read(),1) solve(); return 0; }
T3 Bomber Man wants to bomb an Array.
直接DP,发现一个转移是否合法只取决于区间内是否恰好有一个点。
#include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } typedef long long ll; const int maxn=2010; double score(int len) {return log2(len);} int n,m,S[maxn]; double f[maxn]; void solve() { n=read();m=read(); memset(S,0,sizeof(S)); rep(i,1,m) S[read()+1]++; rep(i,1,n) S[i]+=S[i-1]; f[0]=0.0; rep(i,1,n) { f[i]=0.0; rep(j,0,i-1) if(S[i]-S[j]==1) f[i]=max(f[i],f[j]+score(i-j)); } printf("%.0lf\n",floor(1000000*f[n])); } int main() { dwn(T,read(),1) solve(); return 0; }
T4 xiaoxin and his watermelon candy
先暴力哈希,然后转化成区间不同数的个数查询,离线树状数组随便做做。
#include<cstdio> #include<cstring> #include<cctype> #include<ctime> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=Getchar(); for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1; for(;isdigit(c);c=Getchar()) x=x*10+c-'0'; return x*f; } typedef long long ll; typedef unsigned long long ull; const int maxn=200010; ull X,val[maxn],tmp[maxn]; int n,m,A[maxn]; struct Query { int l,r,id; bool operator < (const Query& ths) const { return l<ths.l; } }Q[maxn]; int last[maxn],f[maxn]; int sumv[maxn],ans[maxn]; int sum(int x) {int res=0;for(;x;x-=x&-x) res+=sumv[x];return res;} void add(int x,int v) {for(;x<=n;x+=x&-x) sumv[x]+=v;} void solve() { n=read(); rep(i,1,n) A[i]=read()+1,sumv[i]=0; if(n>=3) { rep(i,1,n-2) { if(A[i]<=A[i+1]&&A[i+1]<=A[i+2]) val[i]=X*X*A[i]+X*A[i+1]+(ull)A[i+2]; else val[i]=0; tmp[i]=val[i]; } sort(tmp+1,tmp+n-1); rep(i,1,n-2) { if(!val[i]) A[i]=0; else A[i]=lower_bound(tmp+1,tmp+n-1,val[i])-tmp; } rep(i,0,n) last[i]=n+1; dwn(i,n-2,1) f[i]=last[A[i]],last[A[i]]=i; rep(i,1,n) if(last[i]<n) add(last[i],1); m=read(); rep(i,1,m) Q[Q[i].id=i].l=read(),Q[i].r=read()-2; sort(Q+1,Q+m+1);int cur=1; rep(i,1,m) { while(cur<Q[i].l&&cur<=n-2) { if(A[cur]) add(cur,-1),add(f[cur],1); cur++; } if(Q[i].l<=Q[i].r) ans[Q[i].id]=sum(Q[i].r)-sum(Q[i].l-1); else ans[Q[i].id]=0; } rep(i,1,m) printf("%d\n",ans[i]); } else { m=read(); rep(i,1,m) read(),read(),printf("%d\n",0); } } int main() { X=52501;srand(time(0)); dwn(i,rand()%10+5,1) X=X*233333; dwn(T,read(),1) solve(); return 0; }