模拟赛
串(string)
【题目描述】
给定一个由小写字母组成的字符串 s,每次你可以删去它的一个非回文子串,
求删成空串的最小次数。
【输入数据】
第一行一个整数 t 表示数据组数。
每组数据第一行一个整数 n 表示字符串长度,第二行一个字符串 s。
【输出数据】
每组数据输出一行一个整数表示答案,如果无法删成空串输出-1。
【样例输入】
2
7
abcdcba
3
xxx
【样例输出】
2
-1
【样例解释】
对于第一个样例,一种最优方案为 abcdcba->adcba->空串。
【数据范围】
对于 30%的数据,n<=10。
对于 60%的数据,n<=100。
对于 100%的数据,t<=20,n<=10^5。
#include<iostream> #include<cstdio> #include<cstring> #define maxn 110 #define INF 0x7fffffff using namespace std; int ans; struct node{ string s; int len; }; void solve(node now,int step){//已经进行了step次 if(step>=ans)return; for(int l=0;l<now.len;l++){ for(int r=l+1;r<now.len;r++){ int ll=l,rr=r;bool flag=0; while(ll<=rr){ if(now.s[ll]!=now.s[rr]){flag=1;break;} else ll++,rr--; } if(flag==0)continue; node nxt;nxt.s="";nxt.len=0; for(int i=0;i<l;i++)nxt.s+=now.s[i],nxt.len++; for(int i=r+1;i<now.len;i++)nxt.s+=now.s[i],nxt.len++; if(nxt.len==0){ ans=min(ans,step+1); return; } solve(nxt,step+1); } } } int main(){ // freopen("Cola.txt","r",stdin); freopen("string.in","r",stdin);freopen("string.out","w",stdout); int T; scanf("%d",&T); while(T--){ ans=INF; node str; scanf("%d",&str.len);cin>>str.s; solve(str,0); if(ans<INF)printf("%d\n",ans); else puts("-1"); } return 0; }
/* 首先如果s不是回文串答案为1。 考虑对于1<=i<n,是否都满足s[1..i]和s[i+1..n]至少有一个是回文的。如果不满足那么答案为2。 如果满足的话,如果s[1]=s[2],那么s只会形如aaaaa或aaabaaa;如果s[1]!=s[2],那么s只会形如abababa。这三种情况都是无解的。 */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n; char s[100010]; int main(){ freopen("string10.in","r",stdin); int T; scanf("%d",&T); while(T--){ scanf("%d%s",&n,s+1); int l=1,r=n; bool flag=0; while(l<=r){ if(s[l]!=s[r]){flag=1;break;}//不是回文串 l++,r--; } if(flag){puts("1");continue;} for(int i=1;i<=n;i++){//枚举中间点 l=1,r=i; bool flag1=0,flag2=0; while(l<=r){ if(s[l]!=s[r]){flag1=1;break;} l++,r--; } if(flag1==0)continue; l=i+1,r=n; while(l<=r){ if(s[l]!=s[r]){flag2=1;break;} l++;r--; } if(flag1&&flag2){flag=1;puts("2");break;} } if(!flag)puts("-1"); } return 0; }
变量(variable)
【题目描述】
有 n 个变量 w[1]~w[n],每个变量可以取 W 或-W。
有 p 个式子,形如 Hi=ai|w[xi]-w[yi]|+bi|w[yi]-w[zi]|+ci|w[zi]-w[xi]|
+di(w[xi]-w[yi])+ei(w[yi]-w[zi])+fi(w[zi]-w[xi])。
有 q 个条件,形如 w[x]<=w[y]或 w[x]=w[y]或 w[x]<w[y]。
最小化 sigma(wi)+sigma(Hi)。
【输入数据】
第一行一个整数 t 表示数据组数。
每组数据第一行四个整数 n,W,p,q 表示节点数。
接下来 p 行每行九个整数 xi,yi,zi,ai,bi,ci,di,ei,fi。
接下来 q 行每行三个整数 x,y,r。
r=0 表示 w[x]<=w[y];r=1 表示 w[x]=w[y];r=2 表示 w[x]<w[y]。
保证存在方案。
【输出数据】
每组数据输出一行一个整数表示 sigma(wi)+sigma(Hi)的最小值。
【样例输入】
1
3 1 1 1
1 2 3 1 1 1 1 1 1
1 2 2
【样例输出】
3
【数据范围】
对于 30%的数据,n<=15,p,q<=20。
对于 100%的数据,t<=10,n<=500,p,q<=1000,1<=W<=10^6,
0<=ai,bi,ci,di,ei,fi<=1000。
取石子(stone)
【题目描述】
有 n 堆石子,第 i 堆有 xi 个。
Alice 和 Bob 轮流取石子(先后手未定),Alice 每次从一堆中取走 a 个,Bob
每次从一堆中取走 b 个,无法操作者输。
不难发现只会有四种情况:Alice 必胜;Bob 必胜;先手必胜;后手必胜。
你需要选定若干堆石子(共有 2^n 种方案),Alice 和 Bob 只能在你选出的堆
中取,问以上四种情况对应的方案数。
【输入数据】
第一行三个整数 n,a,b,第二行 n 个整数 x1~xn。
【输出数据】
一行四个整数,分别表示 Alice 必胜、Bob 必胜、先手必胜和后手必胜的方
案数,对 10^9+7 取模。
【样例输入】
2 2 3
2 3
【样例输出】
2 0 1 1
【样例解释】
选定空集时后手必胜,选定{2}时 Alice 必胜,选定{3}时先手必胜,选定{2,3}时 Alice
必胜。
【数据范围】
对于 10%的数据,n,xi<=5。
对于 50%的数据,n<=20。
对于另外 10%的数据,a=b。
对于又另外 20%的数据,a=1。
对于 100%的数据,1<=n<=100000,1<=a,b,xi<=10^9。