趣味算法实习:踩气球第二周-《一道很简单的题目》解题报告&AC代码

解题报告:

首先…这个题不是一般的蛋疼,第一问跟后面的处理一点关系都没有- -

先说前面的处理吧:学了对数函数,我们知道:ln(x^a)=aln(x)。所以ln(x!)=Σln(i),i=1,...,x。

又有:一个整数n的位数=lg(n)+1,所以我们可以用如下代码计算N!的位数:

for(i = 0; i != N; ++i)
{
	//注意!在math.h中,log()函数是以e为底的对数,log10()才是以10为底!
	ans += log10((double)i + 1);
}
ans++;

接下来的工作又分为两部分:翻转数列和顺序移动数列。

首先我们已经生成了一个顺序数列{An}。(题目中的意思就是An=1,2,...。和前面的N!没关系- -)

翻转数列:创建一个buf暂存数组,将原数列a-b位拷贝进去,再反向拷贝回去就行了。

顺序移动:创建一个buf暂存数组,将从b倒数第w位到正数第b位存在buf前部,剩下的顺序存在后部,再拷贝回去就行了。

AC代码:

#include <iostream>
#include <math.h>
using namespace std;
int main()
{
	int i, j;
	int N, M, S, K;
	int num[10001];
	double tmp = 0.0;
	cin >> N >> M >> S >> K;
	for(i = 0; i != N; ++i)
	{
		//注意!在math.h中,log()函数是以e为底的对数,log10()才是以10为底!
		tmp += log10((double)(i + 1));
	}
	tmp++;
	int res = (int)tmp;
	for(i = 0; i != M; ++i)
	{
		num[i] = i + 1;
	}
	for(i = 0; i != S; ++i)
	{
		int mode;
		int a, b, w, mark = 0;
		int buf[10001];
		cin >> mode;
		switch(mode)
		{
		case 1:
			mark = 0;
			cin >> a >> b;
			if(a > b) swap(a, b);
			for(j = a - 1; j != b; ++j)
			{
				buf[mark] = num[j]; //拷贝到buf中
				mark++;
			}
			for(j = 0; j != mark; ++j)
			{
				num[b - j - 1] = buf[j]; //逆序拷贝回去
			}
			break;
		case 2:
			mark = 0;
			cin >> a >> b >> w;
			if(a > b) swap(a, b);
			w = w % (b - a + 1);
			if(w == 0) break;
			for(j = b - w; j != b; ++j)
			{
				buf[mark] = num[j]; //拷贝从b倒数第w位到第b位。
				mark++;
			}
			for(j = a - 1; j != b - w; ++j)
			{
				buf[mark] = num[j]; //拷贝第a位到上次的前一位
				mark++;
			}
			mark = 0;
			for(j = a - 1; j != b; ++j)
			{
				num[j] = buf[mark]; //拷贝回去
				mark++;
			}
			break;
		}
	}
	cout << res << endl;
	cout << num[K - 1] << endl;
	return 0;
}


下面附上题目:

一道很简单的题目

时间限制:
1000ms
内存限制:
10000kB
描述

“御坂做了上一周的踩气球,竟然觉得十分easy,御坂吐槽道”。

在学园都市的御坂网络中充满了对于上一周的题目过于简单的各种谴责,于是乎御坂10031做出了一个十分重要的决定——出更简单的题。

“在上一周的基础上,御坂想知道N的阶乘有多少位,并且御坂给出了一个长为M的序列,一开始是顺序排列的,为1到M,御坂可以对这个序列进行两种操作,

第一种操作时对第A位和第B位之间的数进行翻转操作(翻转就是1 2 3 变成3 2 1)

第二种操作是对第A位和第B位之间的数顺序移动W位,

在经过了S次操作之后,御坂想知道最后在第K位的数是哪一个数,御坂碎碎念。”


输入
第一行一个数N,表示需要求出N的阶乘的位数,N<=200000
第二行三个数M,S,K,分别表示序列的长度,操作的次数,最后需要知道答案的第K位数 (M,K<=10000,S<=5000)
接下来S行,每行第一个数表示操作序号,
如果为1,后接两个数A,B,对第A位和第B位之间的数进行翻转操作,
如果为2,后接三个数A,B,W,对第A位和第B位之间的数顺序移动W位
输出
第一行一个数,表示N阶乘的位数
第二行一个数,表示操作结束后第K位是几




提示
序列经过3次操作后的结果分别是
3 2 1 4
1 4 3 2
1 3 4 2
所以最后答案是3

御坂才不会提示你第一个问题可以用log做呢。 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值