2017-10-06清北模拟赛
NOIP 模拟赛
2017 年10 ⽉6 ⽇
题⽬名称排序同余⽅程组字符串
可执⾏⽂件名sort mod str
输⼊⽂件名sort.in mod.in str.in
输出⽂件名sort.out mod.out str.out
每个测试点时限1 秒1 秒1 秒
内存限制256MB 256MB 256MB
测试点数⽬10 10 10
每个测试点分值10 10 10
是否有Special Judge ⽆⽆⽆
题⽬类型传统型传统型传统型
是否有附加⽂件否否否
C++ 语⾔⽂件名后缀cpp cpp cpp
C 语⾔⽂件名后缀c c c
Pascal 语⾔⽂件名后缀pas pas pas
编译开关
对于C++ 语⾔-lm
对于C 语⾔-lm
对于Pascal 语⾔-lm
T1 排序
sort.in/.out/.cpp
【问题描述】
⼩Z 有⼀个数字序列a1; a2; : : : ; an,长度为n,⼩Z 只有⼀个操作:选
定p(1 p n),然后把ap 从序列⾥拿出,然后再插⼊到序列中任意位置。
⽐如a 序列为1,2,4,5,3,p = 5,可以取出3,然后在任意位置插⼊,可
以变为1,2,3,4,5。
现在给你⼀个序列a,问你是否可以通过⼀次操作把整个序列从⼩到⼤
排好序(变成不降的)。
【输入格式】
第⼀⾏⼀个整数n,第⼆⾏空格隔开的n 个整数,代表a 序列。
【输出格式】
如果可以⼀次操作可以排好序,输出”YES”,否则输出”NO”。
【样例输入】
5
1 2 4 5 3
【样例输出】
YES
【数据规模和约定】
对于30% 的数据,满⾜n 1000。
对于60% 的数据,满⾜n 105。
对于100% 的数据,满⾜n 106; 1 ai 106。
2
1 /* 2 要求判断调整后的序列是否可以成为非严格单调递增的 3 sort一下 因为要求只调换一个数字的位置 4 可以发现只能有一个数向后或向前,移动,或者是没有数字移动 5 (排序前后的位置) 6 */ 7 #include <algorithm> 8 #include <cstdio> 9 10 inline void read(int &x) 11 { 12 x=0; register char ch=getchar(); 13 for(; ch>'9'||ch<'0'; ) ch=getchar(); 14 for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0'; 15 } 16 const int N(1e6+5); 17 int n,cnt1,cnt2; 18 struct Sort { 19 int num,pos; 20 bool operator < (const Sort &x)const 21 { 22 if(num!=x.num) return num<x.num; 23 return pos<x.pos; 24 } 25 }a[N]; 26 27 int Presist() 28 { 29 // freopen("sort.in","r",stdin); 30 // freopen("sort.out","w",stdout); 31 read(n); 32 for(int i=1; i<=n; ++i) 33 read(a[i].num),a[i].pos=i; 34 std::sort(a+1,a+n+1); 35 for(int i=1; i<=n; ++i) 36 { 37 if(a[i].pos>i) cnt1++; 38 if(a[i].pos<i) cnt2++; 39 } 40 if(cnt1==1||cnt2==1||(!cnt2&&!cnt1)) puts("YES"); 41 else puts("NO"); 42 return 0; 43 } 44 45 int Aptal=Presist(); 46 int main(int argc,char*argv[]){;}
T2 同余方程组
mod.in/.out/.cpp
【问题描述】
求关于x 的同余⽅程组
x%a1 = b1
x%a2 = b2
x%a3 = b3
x%a4 = b4
的⼤于等于0 的最⼩整数解。
【输入格式】
⼀⾏8 个整数,表⽰a1; b1; a2; b2; a3; b3; a4; b4。
【输出格式】
⼀⾏⼀个整数,答案除以p 的余数。
【样例输入】
2 0 3 1 5 0 7 3
【样例输出】
10
【数据规模和约定】
对于30% 的数据,ai 40, 保证ai 均为素数。
3
对于60% 的数据,1 ai 103, 保证ai 均互素。
对于100% 的数据,0 bi < ai; 1 ai 103。
4
1 /* 2 CRT不互质情况 的模板 3 */ 4 #include <cstdio> 5 6 #ifdef WIN32 7 #define L_ "%I64d" 8 #else 9 #define L_ "%lld" 10 #endif 11 #define LL long long 12 inline void read(LL &x) 13 { 14 x=0; register char ch=getchar(); 15 for(; ch>'9'||ch<'0'; ) ch=getchar(); 16 for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0'; 17 } 18 LL p[5],m[5]; 19 20 LL exgcd(LL a,LL b,LL &x,LL &y) 21 { 22 if(!b) { x=1,y=0; return a; } 23 LL ret=exgcd(b,a%b,x,y),tmp=x; 24 x=y; y=tmp-a/b*y; return ret; 25 } 26 inline LL CRT() 27 { 28 LL x,y,b,c,gcd,tmp; 29 LL ret=m[1],a=p[1],mod; 30 for(int i=2; i<5; ++i) 31 { 32 tmp=m[i];b=p[i];c=tmp-ret; 33 gcd=exgcd(a,b,x,y); 34 x*=c/gcd; mod=b/gcd; 35 x=(x%mod+mod)%mod; 36 ret+=a*x; a*=mod; 37 } 38 return ret?ret:(ret+a); 39 } 40 41 int Presist() 42 { 43 // freopen("mod.in","r",stdin); 44 // freopen("mod.out","w",stdout); 45 for(int i=1; i<5; ++i) 46 read(p[i]),read(m[i]); 47 printf(L_ "\n",CRT()); 48 return 0; 49 } 50 51 int Aptal=Presist(); 52 int main(int argc,char**argv){;}
T3 字符串
str.in/.out/.cpp
【问题描述】
如果把⼀个字符串从头到尾翻转后和原字符串相等,我们称之为回⽂
串,⽐如“aabaa”、“())(”、“2017102”。
如果⼀个字符串存在两个出现过的字母出现的次数相等,我们称之为好
的字符串。
现在给⼀个由⼩写字母组成的字符串,问在这个字符串的所有连续⼦串
中,好的回⽂串有多少个。(两个相同的回⽂串出现在不同位置算多次)。
【输入格式】
⼀⾏⼀个⼩写字母组成的字符串。
【输出格式】
⼀⾏⼀个整数,表⽰答案。
【样例输入】
abcbaabcba
【样例输出】
6
【样例解释】
abcba s[1..5] a,b 出现次数相等
baab s[4..7] a,b 出现次数相等
cbaabc s[3..8] a,b 出现次数相等
bcbaabcb s[2..9] a,c 出现次数相等
5
abcbaabcba s[1..10] a,b 出现次数相等
abcba s[6..10] a,b 出现次数相等
【数据规模和约定】
len 表⽰字符串长度。
对于30% 的数据, len 102。
对于60% 的数据, len 103。
对于100% 的数据,1 len 104。
6
(完)
7
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 5 const int N(1e4+5); 6 int n,ans,tmp[26]; 7 char s[N]; 8 9 int Presist() 10 { 11 // freopen("str.in","r",stdin); 12 // freopen("str.out","w",stdout); 13 scanf("%s",s+1); n=strlen(s+1); 14 for(int l=1; l<n; ++l) 15 for(int r=l+1; r<=n; ++r) 16 { 17 if(r-l+1<4) continue; //判断是否可能存在至少两种相同次数的不同字母 18 memset(tmp,0,sizeof(tmp)); //memset复发度o(n),数组开大就是30,该刚好就60 19 for(int i=l,j=r; i<=j; i++,j--) 20 { 21 if(s[i]!=s[j]) goto love; 22 if(i==j) tmp[s[i]-'a']++; //长度奇数,中间的只会有统计一次 23 else tmp[s[i]-'a']+=2; 24 } 25 std::sort(tmp,tmp+26); 26 for(int k=1; k<26; ++k) 27 if(tmp[k]>1&&tmp[k]==tmp[k-1]) { ans++; break; } 28 love:; 29 } 30 printf("%d\n",ans); 31 return 0; 32 } 33 34 int Aptal=Presist(); 35 int main(int argc,char**argv){;}
1 /* 2 hash 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #include <map> 8 using namespace std; 9 10 typedef unsigned long long ULL; 11 typedef long long LL; 12 13 char s[10005]; 14 ULL h[10005],rh[10005],pw[10005]; 15 int L; 16 17 ULL hs(int l,int r) 18 { 19 return h[r]-h[l-1]*pw[r-l+1]; 20 } 21 ULL rhs(int l,int r) 22 { 23 return rh[l] - rh[r+1]*pw[r-l+1]; 24 } 25 struct N 26 { 27 int a[26]; 28 bool ok() 29 { 30 int b[26]; 31 for(int i=0; i<26; i++) b[i]=a[i]; 32 sort(b,b+26); 33 for(int i=0; i<25; i++) 34 { 35 if(b[i]>0&& b[i] == b[i+1]) return true; 36 } 37 return false; 38 } 39 void clear() 40 { 41 memset(a,0,sizeof a); 42 } 43 }; 44 LL ans=0; 45 map<ULL,LL> num; 46 map<ULL,N> A; 47 void solve_odd() 48 { 49 for(int i=1; i<=L; i++) 50 { 51 int l = 1,r = min(i,L-i+1)+1; 52 while(r-l>1) 53 { 54 int mid = (l+r)/2; 55 if(hs(i-mid+1,i+mid-1)== rhs(i-mid+1,i+mid-1)) l=mid; 56 else r=mid; 57 } 58 int p=l; 59 int tmp = p; 60 while(tmp>=1&&num.find(hs(i-tmp+1,i+tmp-1))==num.end()) tmp--; 61 LL sum = 0; 62 N st; 63 st.clear(); 64 if(tmp>=1) 65 { 66 sum=num[hs(i-tmp+1,i+tmp-1)]; 67 st = A[hs(i-tmp+1,i+tmp-1)]; 68 } 69 while(tmp<p) 70 { 71 st.a[s[i+tmp]-'a']+= (tmp == 0?1:2); 72 if(st.ok()) sum++; 73 num[hs(i-tmp,i+tmp)] = sum; 74 A[hs(i-tmp,i+tmp)] = st; 75 tmp++; 76 } 77 ans+=sum; 78 // printf("# %d %lld\n",i,sum); 79 } 80 } 81 void solve_even() 82 { 83 A.clear(); 84 num.clear(); 85 for(int i=1; i<L; i++) 86 { 87 // printf("### %d\n",i); 88 int l = 1,r = min(i,L-i)+1; 89 while(r-l>1) 90 { 91 int mid = (l+r)/2; 92 if(hs(i-mid+1,i+mid)== rhs(i-mid+1,i+mid)) l=mid; 93 else r=mid; 94 } 95 int p=l; 96 int tmp = p; 97 while(tmp>=1&&num.find(hs(i-tmp+1,i+tmp))==num.end()) tmp--; 98 LL sum = 0; 99 N st; 100 st.clear(); 101 // printf("## %d\n",p); 102 if(tmp>=1) 103 { 104 sum=num[hs(i-tmp+1,i+tmp)]; 105 st = A[hs(i-tmp+1,i+tmp)]; 106 } 107 while(tmp<p) 108 { 109 // printf("# %d %lld\n",tmp,sum); 110 st.a[s[i+tmp+1]-'a']+= 2; 111 if(st.ok()) sum++; 112 num[hs(i-tmp,i+tmp+1)] = sum; 113 A[hs(i-tmp,i+tmp+1)] = st; 114 tmp++; 115 } 116 ans+=sum; 117 // printf("# %d %lld\n",i,sum); 118 } 119 } 120 121 int main() 122 { 123 freopen("str.in","r",stdin); 124 freopen("str.out","w",stdout); 125 scanf("%s",s+1); 126 L=strlen(s+1); 127 s[0]='#'; 128 pw[0]=1; 129 for(int i=1; i<=L; i++) pw[i] = pw[i-1]*13131 ; 130 for(int i=1; i<=L; i++) h[i] = h[i-1]*13131 + s[i]; 131 for(int i=L; i>=1; i--) rh[i] = rh[i+1]*13131 + s[i]; 132 solve_odd(); 133 solve_even(); 134 printf("%lld\n",ans); 135 fclose(stdout); 136 return 0; 137 }