noip2014普及组复赛题解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1.珠心算测验

注意看清题意:其中有多少个数,恰好等于集合中另外两个(不同

的)数之和。这样的题意加上100的规模,建议暴力3个for:

#include

#include

#include

#include

using namespace std;

int n;

int a[105];

int main(){

freopen("count.in","r",stdin);

freopen("count.out","w",stdout);

scanf("%d",&n);

for(int i=1; i<=n; i++){

scanf("%d",&a[i]);

}

sort(a+1,a+n+1);

int res=0;

for(int i=1; i<=n; i++){

int ok=0;

for(int j=1; j<=n && !ok; j++) if(j!=i){

for(int k=1; k<=n && !ok; k++) if(a[k]!=a[j]){

if(a[j]+a[k]==a[i]) ok=1;

}

}

res+=ok;

}

printf("%d\n",res);

return 0;

}

2.比例简化

L很小,还是枚举,然后比较的话建议用乘法比较,避免精度问题:#include

#include

#include

using namespace std;

int A,B,L;

int gcd(int a,int b){

if(b==0) return a;

return gcd(b,a%b);

}

int main(){

freopen("ratio.in","r",stdin);

freopen("ratio.out","w",stdout);

scanf("%d%d%d",&A,&B,&L);

int ba=1000000,bb=1;

for(int i=1; i<=L; i++){

for(int j=1; j<=L; j++){

if(gcd(i,j)==1 && i*B>=j*A){

if(ba*j>=bb*i){

ba=i, bb=j;

}

}

}

}

printf("%d %d\n",ba,bb);

return 0;

}

3.螺旋矩阵

没一圈的数量有规律的,最外面一圈(n-1)*4,然后每往里n-2,直到后要么只有一个点,要么4个点。

所以可以先确定是在哪圈里,然后暴力走一圈就行:

#include

#include

#include

using namespace std;

int n,x,y;

int solve(){

scanf("%d%d%d",&n,&x,&y);

int ceng=min(x, n+1-x);

ceng=min(ceng, min(y, n+1-y));

int num=0, len=n-1;

for(int i=1; i

int ad;

if(len==0) ad=1;

else ad=len*4;

num+=ad;

}

num++;

int nx=ceng, ny=ceng;

if(nx==x && ny==y) return num;

for(int i=1; i<=len; i++) {

ny++; num++;

if(nx==x && ny==y) return num;

}

for(int i=1; i<=len; i++){

nx++; num++;

if(nx==x && ny==y) return num;

}

for(int i=1; i<=len; i++){

ny--; num++;

if(nx==x && ny==y) return num;

}

for(int i=1; i

nx--; num++;

if(nx==x && ny==y) return num;

}

return -1;

}

int main(){

freopen("matrix.in","r",stdin);

freopen("matrix.out","w",stdout);

int res=solve();

printf("%d\n",res);

return 0;

}

4.子矩阵

可以用二进制状态枚举取了哪些列,然后对于行的选取,可以DP,预处理每一行的代价,任意两行之间的代价,那么

dp[j][i]=min(dp[j][i], dp[k][i-1]+val[k][j]+dp[j][1]);

代码写的不是很顺,为了调试写了很多输出注释语句:

#include

#include

#include

#include

using namespace std;

int g[25][25],f[25][25],dp[25][25],val[25][25];

int n,m,x,y,res;

int count(int v){

int ret=0;

while(v){

if(v&1) ret++;

v>>=1;

}return ret;

}

void gao(){

//printf("gao\n");

for(int i=1; i<=n; i++){

for(int j=i+1; j<=n; j++){

val[i][j]=0;

for(int k=1; k<=y; k++) val[i][j]+=abs(f[i][k]-f[j][k]);

//printf("%d %d = %d\n",i,j,val[i][j]);

}

}

for(int i=1; i<=x; i++){

for(int j=i; j<=n; j++) dp[j][i]=100000000;

}

for(int i=1; i<=n; i++){

dp[i][1]=0;

for(int j=2; j<=y; j++){

dp[i][1]+=abs(f[i][j]-f[i][j-1]);

}

}

//printf("ok\n");

for(int i=2; i<=x; i++){

for(int j=i; j<=n; j++){

//dp[j][i]=100000000;

for(int k=i-1; k

dp[j][i]=min(dp[j][i],

dp[k][i-1]+val[k][j]+dp[j][1]);

相关文档
最新文档