Codeforces Round #184 (Div. 2) D、E
2013-05-24 08:17
417 查看
D题根据题目描述,图中只能存在两类边:第一类,对于所有的 i (1<=i<n) 都存在边 i-->i+1;第二类,对于 i 可以存在边 i-->i+k+1 (i>=1 && i+k+1<=n),若边 x-->x+k+1 存在,则不能存在这样的边 y-->y+k+1 (y>=x+k+1)。弄清楚这些后,剩下的就是常规的排列组合了。代码如下(比较挫):
E题,首先找出字符串中所有回文子串的中心,将对应位置的字母替换为 1 ,其余字母替换为 0 。 比如 abacaba 对应的01串为 0101010 。那么问题就转化为:两人轮流取 1 ,最后不能取者,败。取 1 的规则如下:每次至少取1个,如果取走的位置的左右有 1 则也同时取走。被0相互分割的 1 是相互独立的。这显然是一个无偏博弈,用SG函数就可以解决了。
#include<stdio.h> #include<iostream> using namespace std; #define MOD 1000000007 bool Is[1000010]; long long quickpow(long long i,long long x); long long run(long long L,long long R,long long K); int main() { int n,m,k,l,r,L,R; bool flag=true; long long ans; l=r=0; scanf("%d%d%d",&n,&m,&k); for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); if(flag && v!=u+1) { if(v-u-k!=1) { flag=false; continue; } Is[u]=true; if(l==0) l=r=u; else r=u; } } if(flag==false) { printf("0\n"); return 0; } if(l==0) { if(n-(k+1)*2>=0) { ans=quickpow(k,2); ans=((ans*2)%MOD+((n-(k+1)*2)*ans)%MOD)%MOD; printf("%lld\n",ans); } else if(n-k-1>=0) { ans=quickpow(n-k-1,2); printf("%lld\n",ans); } else printf("1\n"); return 0; } if(r-l>k) printf("0\n"); else { L=max(r-k,1),R=min(l+k,n-k-1); ans=run(L,R,k); printf("%lld\n",ans); } return 0; } long long run(long long L,long long R,long long K) { long long rt,cnt; cnt=0; for(int i=L;i<=L+K && i<=R;i++) if(Is[i]==false) cnt++; rt=quickpow(cnt,2); for(int i=L+1;i<=R-K;i++) { if(Is[i-1]==false) cnt--; if(Is[i+K]==false) { rt=(rt+quickpow(cnt,2))%MOD; cnt++; } } return rt; } long long quickpow(long long i,long long x) { if(i==0) return 1; if(i==1) return x; if(i==2) return x*x; long long rt=quickpow(i/2,x); if(i%2==0) rt=(rt*rt)%MOD; else rt=((rt*rt)%MOD*x)%MOD; return rt; }
E题,首先找出字符串中所有回文子串的中心,将对应位置的字母替换为 1 ,其余字母替换为 0 。 比如 abacaba 对应的01串为 0101010 。那么问题就转化为:两人轮流取 1 ,最后不能取者,败。取 1 的规则如下:每次至少取1个,如果取走的位置的左右有 1 则也同时取走。被0相互分割的 1 是相互独立的。这显然是一个无偏博弈,用SG函数就可以解决了。
#include<stdio.h> #include<iostream> #include<string.h> using namespace std; #define MAXN 5010 int SG[MAXN],F[MAXN],len,ans; char str[MAXN]; void Init(); bool check(int n); int main() { scanf("%s",str); len=strlen(str); Init(); for(int i=1;i<len-1;) { if(str[i-1]==str[i+1]) { int num=1; for(int j=i+1;j<len-1;j++) if(str[j-1]!=str[j+1]) break; else num++; ans^=SG[num]; i+=num; } else i++; } if(ans==0) printf("Second\n"); else { for(int i=1;i<len-1;i++) if(str[i-1]==str[i+1] && check(i)) { printf("First\n%d\n",i+1); break; } } return 0; } void Init() { for(int i=1;i<=len;i++) { for(int j=1;j<=(i+1)/2;j++) { F[SG[max(j-2,0)]^SG[max(i-j-1,0)]]=i; } while(F[SG[i]]==i) SG[i]++; } } bool check(int n) { int rt,i,l,r; rt=ans; l=r=0; for(i=n-1;i>0;i--) if(str[i-1]==str[i+1]) l++; else break; for(i=n+1;i<len-1;i++) if(str[i-1]==str[i+1]) r++; else break; rt=rt^SG[1+l+r]^SG[max(l-1,0)]^SG[max(r-1,0)]; return rt==0; }
相关文章推荐
- Codeforces Round #184 (Div. 2)——A,B,C
- Codeforces Round #184 (Div. 2) Continued Fractions 分数计算 long long相乘会越界
- Codeforces Round #184 (Div. 2) E. Playing with String(博弈)
- Codeforces Round #184 (Div. 2)
- Codeforces Round #184 (Div. 2)-B. Continued Fractions
- Codeforces Round #184 (Div. 2)
- Codeforces Round #184 (Div. 2) A题
- Codeforces Round #184 (Div. 2) B. Continued Fractions
- 输出判断Codeforces Round #184 (Div. 2)
- Codeforces Round #111 (Div. 2) 160B. Unlucky Ticket(贪心)
- Educational Codeforces Round 34 (Rated for Div. 2) C - Boxes Packing
- Codeforces Round #104 (Div. 2) //缺E
- 【Codeforces Round 370 (Div 2) B】【简单贪心】Memory and Trident
- CodeForces Round 199 Div2
- Codeforces Round #264 (Div. 2) C Gargari and Bishops 【暴力】
- Codeforces Round #387(Div. 2)C. Servers【模拟】
- Codeforces Round #435 (Div. 2) C. Mahmoud and Ehab and the xor
- Codeforces Round #134 (Div. 2) C. Ice Skating
- Codeforces Round #370 (Div. 2) A. Memory and Crow 水题
- Codeforces Round #238 (Div. 2)