2016.11.6 night NOIP模拟赛 考试整理
题目+数据:链接:http://pan.baidu.com/s/1hssN8GG 密码:bjw8
总结:
总分:300分,仅仅拿了120份。
这次所犯的失误:对于2,3题目,我刚刚看就想到了正确思路,急于敲正确思路,而没有去骗基础得分。
结果第二题DP打残了,第三题排列组合漏了一个小点没考虑到,都是仅仅拿了10分。
T1:
1 /* 2 第一题比较容易,注意一些细节就可以了。 3 比如删除前导0不能删没了等等。 4 */ 5 #define N 1500 6 #include<iostream> 7 using namespace std; 8 #include<cstdio> 9 #include<cstring> 10 char a[N],b[N]; 11 int a1[N],b1[N],len; 12 void input() 13 { 14 scanf("%s%s",a+1,b+1); 15 len=strlen(a+1); 16 for(int i=1;i<=len;++i) 17 a1[i]=a[i]-'0'; 18 for(int i=1;i<=len;++i) 19 b1[i]=b[i]-'0'; 20 } 21 int main() 22 { 23 freopen("number.in","r",stdin); 24 freopen("number.out","w",stdout); 25 input(); 26 for(int i=1;i<=len;++i) 27 { 28 if(a1[i]>b1[i]) b1[i]=11; 29 if(a1[i]<b1[i]&&b1[i]!=11) a1[i]=11; 30 } 31 int ia=1,ib=1; 32 bool flag=false; 33 while(ia<len&&(a1[ia]==0||a1[ia]==11)) 34 { 35 if(a1[ia]==0) flag=true; 36 ia++; 37 } 38 if(a1[ia]==11) ia++; 39 if(ia>len&&(!flag)) printf("BOOM"); 40 else{ 41 for(int i=ia;i<=len;++i) 42 if(a1[i]!=11) printf("%d",a1[i]); 43 if(ia>len&&flag) printf("0"); 44 } 45 printf("\n"); 46 flag=false; 47 while(ib<len&&(b1[ib]==0||b1[ib]==11)) 48 { 49 if(b1[ia]==0) flag=true; 50 ib++; 51 } 52 if(b1[ib]==11) ib++; 53 if(ib>len&&(!flag)) printf("BOOM"); 54 else{ 55 for(int i=ib;i<=len;++i) 56 if(b1[i]!=11) printf("%d",b1[i]); 57 if(ib>len&&flag) printf("0"); 58 } 59 fclose(stdin); 60 fclose(stdout); 61 return 0; 62 }
T2:正确做法所用的技巧和NOIP2015Day2子串相同都用到了辅助数组。
哎╮(╯▽╰)╭圆形操场不是成环考虑的。
说明:测试数据中有两组是有问题的,就是当出现偶数组合并不了的时候,是输出了最大值。而zhx大牛的最大值是1e9,因人而异吧。
1 #define N 405 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #include<cstring> 6 typedef long long ll; 7 int n,sum[N]; 8 ll f1[N][N],f2[N][N]; 9 void input() 10 { 11 scanf("%d",&n); 12 int x; 13 for(int i=1;i<=n;++i) 14 { 15 scanf("%d",&x); 16 sum[i]=sum[i-1]+x; 17 } 18 } 19 void DP() 20 { 21 for(int i=1;i<=n;++i) 22 for(int j=1;j<=n;++j) 23 f1[i][j]=f2[i][j]=(1<<31)-1; 24 for(int i=1;i<=n-1;++i) 25 f2[i][i+1]=sum[i+1]-sum[i-1]; 26 for(int i=1;i<=n;++i) 27 f1[i][i]=0; 28 for(int len=3;len<=n;++len) 29 for(int i=1;i+len-1<=n;++i) 30 { 31 int j=i+len-1; 32 for(int k=i;k<j;++k) f2[i][j]=min(f2[i][j],f1[i][k]+f1[k+1][j]+sum[j]-sum[i-1]); 33 for(int k=i;k<j;++k) f1[i][j]=min(f1[i][j],f2[i][k]+f1[k+1][j]+sum[j]-sum[k]); 34 /*注意这个推f1这个方程中,所加的代价是sum[j]-sum[k],因为i---k-1,这段石子的花费,我们在推f2的时候已经加过了,所以不能重复加了*/ 35 } 36 } 37 int main() 38 { 39 freopen("merge.in","r",stdin); 40 freopen("merge.out","w",stdout); 41 input(); 42 DP(); 43 cout<<f1[1][n]<<endl; 44 fclose(stdin); 45 fclose(stdout); 46 return 0; 47 }
T3:
1 #define N 100010 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #define mod 1000000007 6 typedef long long ll; 7 int n,m,x,y; 8 bool p1[N],p2[N]; 9 ll jc[N],ny[N]; 10 ll quick_pow(ll a,ll b)//a^b 11 { 12 ll ans=1; 13 while(b) 14 { 15 if(b&1) 16 { 17 ans=(ans*a)%mod; 18 } 19 a=(a*a)%mod; 20 b>>=1; 21 } 22 return ans; 23 } 24 ll Mo(ll x)/*这里定义了一个负数的取模方法,因为负数取模还是负数,所以为了预防结果输出这种不合逻辑的答案,我们需要进行如下处理*/ 25 { 26 if(x>=0&&x<mod) return x; 27 x%=mod; 28 if(x<0) x+=mod; 29 return x; 30 } 31 ll C(int n,int m) 32 { 33 if(m>n||m<0) return 0; 34 if(m==n||m==0) return 1; 35 return jc[n]*ny[m]%mod*ny[n-m]%mod; 36 } 37 int main() 38 { 39 freopen("problem.in","r",stdin); 40 freopen("problem.out","w",stdout); 41 scanf("%d%d",&n,&m); 42 for(int i=1;i<=m;++i) 43 { 44 scanf("%d%d",&x,&y); 45 if(x==y) 46 { 47 printf("0"); 48 return 0; 49 } 50 p1[x]=true;p2[y]=true; 51 } 52 int s=0; 53 for(int i=1;i<=n;++i) 54 { 55 if(!p1[i]&&!p2[i]) s++;/*统计可以自由放的个数*/ 56 } 57 jc[0]=1; 58 for(int i=1;i<=n;++i) jc[i]=(jc[i-1]*i)%mod; 59 for(int i=0;i<=n;++i) ny[i]=quick_pow(jc[i],mod-2); 60 ll ans=jc[n-m]; 61 for(int i=1;i<=s;++i) 62 { 63 if(i&1) ans=Mo(ans-C(s,i)*jc[n-m-i]); 64 else ans=Mo(ans+C(s,i)*jc[n-m-i]); 65 } 66 cout<<ans<<endl; 67 fclose(stdin); 68 fclose(stdout); 69 return 0; 70 }