CodeVS天梯白银

2016.8.12

【背景】
        为了迎接即将到来的NOIP2016,我决定爆刷CodeVS的天梯,今天爆刷了11道白银水题。其实说是水题,有些还挺有意思的,比如1012、1011。
【题解】
> 1011 数的计算
- f[i]表示输入i时应该输出的答案,易得f[i]=∑f[j]( j=1 to (i div 2) ),这样是 O(N^2)的,可以维护一个f的前缀和s[i],转移变为f[i]=s[i div 2],复杂度O(N)
(PS:后来我出了一道题,就是这道题的升级版,link:wyw的数字金字塔)
//CodeVS 1011 数的计算  2001年NOIP全国联赛普及组
#include <cstdio>
using namespace std;
int n, f[1010], s[1010];
int main()
{
	int i, j;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		f[i]=s[i>>1]+1;
		s[i]=s[i-1]+f[i];
	}
	printf("%d",f[n]);
	return 0;
}
> 1012 最大公约数和最小公倍数问题
- 我对数论不敏感。。。所以这道做着有点困难。可以推出题目的等价问题是找无序整 数对(a,b)使得gcd(a,b)=1 且 lcm(a,b)=y0/x0,就是说a和b必须互质且最小公倍数为,那么将t分解质因数t=p1^q1*p2^q2*...*pm^qm,假如a有了里面的一个质因子pi,那么b必须没有这个质因子,且a中这个质因子的指数必须和t中这个质因子的指数相等,只有这样才能同时满足上述条件,同样的b有这个质因子时所有情况相反。也就是说对于任何一个t的质因子pi,且指数为qi。则要么a含有pi的qi次幂,bi中不含有pi;要么a不含pi,b含有pi的qi次幂。对于任何一个pi,都有这两种情况,假如t共有m个质因子,则由乘法原理可知(也可以从二进制的角度来理解),答案就为2^m。综上所述,对t进行质因数分解,分解出m个质因子,答案即为2^m
(PS:后来在一次模拟赛中,我出了道类似的题目:wyw的诅咒
//CodeVS 1012 最大公约数和最小公倍数问题  2001年NOIP全国联赛普及组 数论 
#include <cstdio>
using namespace std;
int main()
{
	int x0, y0, t, ans=1, x;
	scanf("%d%d",&x0,&y0);
	if(y0%x0)
	{
		printf("0\n");
		return 0;
	}
	for(x=2,t=y0/x0;t>1;x++)
	{
		if(t%x==0)ans<<=1;
		while(t%x==0)t/=x;
	}
	printf("%d\n",ans);
	return 0;
}
> 1083 Cantor表
- 把题目中的那张图顺时针旋转45°,可以得到一个金字塔形的东西。不难看出有性质:第i行共有i个数,且第j个数是第i-j+1个数的倒数(j<=i)奇数排从左往右数,偶数排从右往左数,所以我们干脆就全都从左往右数,对于偶数排,直接把求出的答案变成倒数即可。用等差数列求和公式∑(1 to i)=i(i+1)/2,枚举i找到最小的i使得∑(1 to i)>=N,则要求的数就是第i行的第(N-i(i-1)/2)个数,对于奇数排,答案就是(i+1-N)/N,偶数排取倒数即可。
//CodeVS1083 NOIP1999 Cantor表 水题模拟 
#include <cstdio>
using namespace std;
int main()
{
	int i, N, a, b;
	scanf("%d",&N);
	for(i=1;(i*(1+i)>>1)<N;i++);
	N-=(i*(i-1)>>1);
	b=N;a=i+1-b;
	if(i&1)printf("%d/%d\n",a,b);
	else printf("%d/%d\n",b,a);
	return 0;
}
> 1160 蛇形矩阵
- 水题模拟不解释
//CodeVS 1160 蛇形矩阵 水题模拟
#include <cstdio>
using namespace std;
int matrix[110][110];
int main()
{
	int N, i, j, cnt, sigma, l, r, u, d;
	scanf("%d",&N);
	cnt=N*N;
	for(i=1;i<=N;i++)matrix[0][i]=matrix[N+1][i]=matrix[i][0]=matrix[i][N+1]=1;
	i=N;j=N;matrix[N][N]=cnt--;
	while(i!=(N+1>>1)||j!=(N+1>>1))
	{
		l=matrix[i][j-1];
		r=matrix[i][j+1];
		u=matrix[i-1][j];
		d=matrix[i+1][j];
		if(!d&&!r)j++;
		else if(!l&&!d)i++;
		else if(!l&&!u)j--;
		else if(!u&&!r)i--;
		else if(!d)i++;
		else if(!l)j--;
		else if(!u)i--;
		else if(!r)j++;
		matrix[i][j]=cnt--;
	}
	for(i=1,sigma=0;i<=N;i++)sigma+=matrix[i][i]+matrix[i][N-i+1];
	for(i=1;i<=N;i++)
	{
		for(j=1;j<=N;j++)printf("%d ",matrix[i][j]);
		printf("\n");
	}
	printf("%d\n",sigma-1);
	return 0;
}
> 1430 素数判定
- 最基本的根号n的素数判定
//CodeVS 1430 素数判定 水题 
#include <cstdio>
using namespace std;
int main()
{
	int x, t, n;
	scanf("%d",&n);
	for(x=2;x*x<=n&&n%x;x++);
	if(x*x<=n)printf("\\n\n");
	else printf("\\t\n");
	return 0;
}
> 1474 十进制转m进制
- 小学生题。。
//CodeVS 1474 十进制转m进制 水题
#include <cstdio>
using namespace std;
int stack[1000], top;
int main()
{
	int n, m;
	scanf("%d%d",&n,&m);
	while(n)
	{
		stack[++top]=n%m;
		n/=m;
	}
	while(top)
		if(stack[top]>=10)printf("%c",stack[top--]-10+'A');
		else printf("%c",stack[top--]+'0');
	printf("\n");
	return 0;
}
> 1475 m进制转十进制
- 同上
//CodeVS 1475 m进制转十进制 水题
#include <cstdio>
#include <cstring>
using namespace std;
int ans, m;
char s[10000];
int main()
{
	int i, x, t;
	scanf("%s%d",s,&m);
	for(i=strlen(s)-1,x=1;i>=0;i--,x*=m)
	{
		if(s[i]>='A')t=s[i]-'A'+10;
		else t=s[i]-'0';
		ans+=t*x;
	}
	printf("%d\n",ans);
	return 0;
}
> 1501 二叉树最大宽度和高度
- 浪费生命的题,必须5分钟A掉
//CodeVS1501 二叉树最大宽度和高度 水题搜索
#include <cstdio>
#include <algorithm>
using namespace std;
int cnt[20], n, maxdep, l[20], r[20], maxlen;
void dfs(int p, int dep)
{
	cnt[dep]++;
	if(l[p])dfs(l[p],dep+1);
	if(r[p])dfs(r[p],dep+1);
	maxdep=max(maxdep,dep);
}
int main()
{
	int i;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d%d",&l[i],&r[i]);
	dfs(1,1);
	maxlen=0;
	for(i=1;i<=maxdep;i++)if(cnt[i]>maxlen)maxlen=cnt[i];
	printf("%d %d\n",maxlen,maxdep);
	return 0;
}
> 1842 递归第一次
- 虽然让用递归,但是根本没必要啊。。这道题连数组都不用
//CodeVS1842 递归第一次 水题
#include <cstdio>
using namespace std;
int main()
{
	int x, a, b, t;
	scanf("%d",&x);
	if(x>=0){printf("5\n");return 0;}
	x=-x;
	a=b=5;
	while(x--)t=a+b+1,a=b,b=t;
	printf("%d\n",b);
	return 0;
}
> 3038 3n+1问题
- 题目说“至今没有人证明对所有的正整数该过程都终止”,也就是说至今也没有发现哪个数无法终止,所以就不用考虑输出-1的情况了。直接写一个递归发现每个数终止的步数还是挺少的。
//CodeVS 3038 3n+1问题 水题
#include <cstdio>
#include <cstdlib>
using namespace std;
int dfs(int x)
{
	if(x==1)return 0;
	if(x&1)return dfs(3*x+1)+1;
	return dfs(x>>1)+1;
}
int main()
{
	int T, n, i, t;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		printf("%d\n",dfs(n));
	}
	return 0;
}
> 3143 二叉树的序遍历
- 水题
//CodeVS 3143 二叉树的序遍历 水题 
#include <cstdio>
using namespace std;
int n, l[100], r[100], tot, s1[100], s2[100], s3[100];
void dfs(int x)
{
	s1[++s1[0]]=x;
	if(l[x])dfs(l[x]);
	s2[++s2[0]]=x;
	if(r[x])dfs(r[x]);
	s3[++s3[0]]=x;
}
int main()
{
	int i;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d%d",&l[i],&r[i]);
	dfs(1);
	for(i=1;i<=n;i++)printf("%d ",s1[i]);printf("\n");
	for(i=1;i<=n;i++)printf("%d ",s2[i]);printf("\n");
	for(i=1;i<=n;i++)printf("%d ",s3[i]);printf("\n");
	return 0;
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值