信息与未来2015真题笔记

[信息与未来 2015] 加数

题目描述

给出一个正整数 n n n,在 n n n 的右边加入 ⌊ n 2 ⌋ \left\lfloor\dfrac n2\right\rfloor 2n,然后在新数的右边
再加入 ⌊ ⌊ n 2 ⌋ 2 ⌋ \left\lfloor\dfrac{\left\lfloor\dfrac n2\right\rfloor}2\right\rfloor 22n ,一直这样进行下去,直到加入的数为 0 0 0 为止(注意, 0 0 0 不应当被加入)。

求加数结束后新数的长度。

输入格式

一行一个整数 n n n

输出格式

一行一个整数,为加数结束后新数的长度。

样例 #1

样例输入 #1

37

样例输出 #1

8

提示

样例解释

  • ⌊ 37 2 ⌋ = 18 \left\lfloor\dfrac{37}2\right\rfloor=18 237=18,加到 n n n 的右边成为 3718 3718 3718
  • ⌊ 18 2 ⌋ = 9 \left\lfloor\dfrac{18}2\right\rfloor=9 218=9,加到新数的右边成为 37189 37189 37189
  • ⌊ 9 2 ⌋ = 4 \left\lfloor\dfrac{9}2\right\rfloor=4 29=4,加到新数的右边成为 371894 371894 371894
  • ⌊ 4 2 ⌋ = 2 \left\lfloor\dfrac{4}2\right\rfloor=2 24=2,加到新数的右边成为 3718942 3718942 3718942
  • ⌊ 2 2 ⌋ = 1 \left\lfloor\dfrac{2}2\right\rfloor=1 22=1,加到新数的右边成为 37189421 37189421 37189421
  • ⌊ 1 2 ⌋ = 0 \left\lfloor\dfrac12\right\rfloor=0 21=0,加数结束,最后得到的数是一个 8 8 8 位数。

数据范围

1 ≤ n ≤ 1 0 5 1\le n\le10^5 1n105

思路

直接模拟,判断位数。

代码

#include <bits/stdc++.h>
//#define int long long
using namespace std;

int n; 
int sum;

void solve()
{
	cin >> n;
	while (n)
	{
		int m = n,num = 0;
		while (m)
			m /= 10,num++;
		sum += num;
		n /= 2;
	}
	cout << sum;
}

signed main()
{
	solve();
	return 0;
}

[信息与未来 2015] 中间值

题目描述

给出一个正整数 n n n,生成长度为 n n n 的数列 a a a,其中 a i = i ( 1 ≤ i ≤ n ) a_i=i(1\le i\le n) ai=i(1in)

  • n n n 为奇数,则输出 a a a 的中间数(位于 a a a 正中位置的数);
  • n n n 为偶数,则输出位于 a a a 中间两个数的和。

输入格式

一个正整数 n n n

输出格式

一个正整数。若 n n n 为奇数,则输出其中间值;若 n n n 为偶数,则输出两个中间值的和。

样例 #1

样例输入 #1

9

样例输出 #1

5

样例 #2

样例输入 #2

10

样例输出 #2

11

提示

1 ≤ n ≤ 1 0 18 1\le n\le10^{18} 1n1018

思路

n n n 为奇数,则答案为 n ÷ 2 + 1 n\div2+1 n÷2+1
n n n 为偶数,则答案为 n + 1 n+1 n+1

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n;

void solve()
{
	cin >> n;
	if (n % 2)
		cout << n/2+1;
	else
		cout << n+1;
}

signed main()
{
	solve();
	return 0;
}

[信息与未来 2015] 买木头

题目描述

n n n 个木材供应商,每个供应商有长度相同的一定数量的木头。长木头可以锯短,但短木头不能接长。有一个客人要求 m m m 根长度相同的木头,要求计算出:此时供货商提供的木头满足客人要求的最大长度是多少。

例如 n = 2 , m = 30 n=2,m=30 n=2,m=30,两个供货商的木头为:

  • 12 , 10 12,10 12,10(第 1 1 1 个供货商的木头长度为 12 12 12,共有 10 10 10 根);
  • 5 , 10 5,10 5,10(第 2 2 2 个供货商的木头长度为 5 5 5,共有 10 10 10 根)。

计算的结果为 5 5 5,即长度为 12 12 12 的木头一根可锯出两根长度为 5 5 5 的木头,多余的无用;长度为 5 5 5 的木头不动,此时,可以得到 30 30 30 根长度为 5 5 5 的木头。

输入格式

一行四个整数 n , m , l 1 , s 1 n,m,l_1,s_1 n,m,l1,s1。其中 l 1 l_1 l1 是第一个供货商木头的长度, s 1 s_1 s1 是第一个供货商木头的数量。其他供货商木头
的长度和数量 l i l_i li s i ( i ≥ 2 ) s_i(i\ge2) si(i2)由下面的公式给出:

  • l i = ( ( l i − 1 × 37011 + 10193 )   m o d   10000 ) + 1 l_i=((l_{i-1}\times37011+10193) \bmod 10000)+1 li=((li1×37011+10193)mod10000)+1
  • s i = ( ( s i − 1 × 73011 + 24793 )   m o d   100 ) + 1 s_i=((s_{i-1}\times73011+24793) \bmod 100)+1 si=((si1×73011+24793)mod100)+1

输出格式

一个整数,即满足要求的 m m m 根长度相同的木头的最大长度。

样例 #1

样例输入 #1

10 10000 8 20

样例输出 #1

201

提示

1 ≤ n ≤ 1 0 4 , 1 ≤ m ≤ 1 0 6 , 1 ≤ l 1 ≤ 1 0 4 , 1 ≤ s 1 ≤ 100 1\le n\le10^4,1\le m\le10^6,1\le l_1\le10^4, 1\le s_1\le100 1n104,1m106,1l1104,1s1100

思路

二分木头的长度,每次 check 判断数量是否足够。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n,m;
int a[10010],b[10010];

bool judge(int x)
{
	int sum = 0;
	for (int i = 1;i <= n;i++)
		sum += a[i]/x*b[i];
	return sum >= m;
}

void solve()
{
	cin >> n >> m >> a[1] >> b[1];
	for (int i = 2;i <= n;i++)
		a[i] = ((a[i-1]*37011+10193)%10000) + 1;
	for (int i = 2;i <= n;i++)
		b[i] = ((b[i-1]*73011+24793)%100) + 1;
	int l = 1,r = 10000,best;
	while (l <= r)
	{
		int mid = (l+r)/2;
		if (judge(mid))
			best = mid,l = mid+1;
		else
			r = mid-1;
	}
	cout << best;
}

signed main()
{
	solve();
	return 0;
}

[信息与未来 2015] 拴奶牛

题目描述

n n n 头奶牛,有 k k k 个木桩,每个木桩有一个位置,一个木桩上只能拴一头奶牛。由于奶牛好斗,所以在拴奶牛的时候,要求距离最近的奶牛的距离尽可能大。

例如 n = 4 , k = 6 n=4,k=6 n=4,k=6,木桩的位置为 0 , 3 , 4 , 7 , 8 , 9 0,3,4,7,8,9 0,3,4,7,8,9,此时为下图。
KaTeX parse error: Unexpected end of input in a macro argument, expected '}' at position 12: \underline\̲t̲e̲x̲t̲{\qquad O\quad …
有许多种拴牛方案,例如:

  • 0 , 3 , 4 , 9 0,3,4,9 0,3,4,9:此时最近距离为 1 1 1 3 , 4 3,4 3,4 之间);
  • 0 , 3 , 7 , 9 0,3,7,9 0,3,7,9:此时最近距离为 2 2 2

输入格式

三个整数 n , k , p 1 n,k,p_1 n,k,p1,其中 p 1 p_1 p1 为第 1 1 1 个木桩的位置,其他木桩 p i ( i ≥ 2 ) p_i(i\ge2) pi(i2) 的位置由下面公式给出:

p i = p i − 1 + ( ( p i − 1 × 2357 + 137 )   m o d   10 ) + 1 p_i = p_{i-1} + ((p_{i-1}\times2357+137) \bmod 10)+1 pi=pi1+((pi1×2357+137)mod10)+1

输出格式

一个整数,即奶牛间最近距离的最大值。

样例 #1

样例输入 #1

25 70 99

样例输出 #1

12

提示

1 ≤ n ≤ k ≤ 1 0 6 , 0 ≤ p 1 ≤ 100 1\le n\le k\le10^6,0\le p_1\le100 1nk106,0p1100

思路

二分两只牛之间的距离,每次 check 判断木桩是否足够。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n,m;
int a[1000010];

bool judge(int x)
{
	int last = 1,num = 1;
	for (int i = 2;i <= m;i++)
		if (a[i]-a[last] >= x)
			num++,last = i;
	return num >= n;
}

void solve()
{
	cin >> n >> m >> a[1];
	for (int i = 2;i <= m;i++)
		a[i] = a[i-1] + ((a[i-1]*2357+137) % 10) + 1;
	int l = 1,r = 1e9,best;
	while (l <= r)
	{
		int mid = (l+r)/2;
		if (judge(mid))
			best = mid,l = mid+1;
		else
			r = mid-1;
	}
	cout << best;
}

signed main()
{
	solve();
	return 0;
}

[信息与未来 2015] 分数计数

题目描述

n n n 个球队,编号为 1 ∼ n 1\sim n 1n,共进行 n n n 场比赛,每场比赛有一个胜队。计分方法如下:

  • 是连胜中的第一次胜利,则本次胜利得 1 1 1 分。
  • 是连胜中的第二次胜利,则本次胜利得 2 2 2 分。
  • 是连胜中的第三次胜利,则本次胜利得 3 3 3 分。
  • 连胜超过三次以上的胜场,每场得 3 3 3 分。

例如 n = 12 n=12 n=12,比赛的胜队为 1 , 2 , 1 , 1 , 3 , 2 , 1 , 1 , 1 , 1 , 4 , 2 1,2,1,1,3,2,1,1,1,1,4,2 1,2,1,1,3,2,1,1,1,1,4,2,计分如下:

  • 1 1 1 1 + 1 + 2 + 1 + 2 + 3 + 3 = 13 1+1+2+1+2+3+3=13 1+1+2+1+2+3+3=13 分;
  • 2 2 2 1 + 1 + 1 = 3 1+1+1=3 1+1+1=3 分;
  • 3 ∼ 4 3\sim 4 34 1 1 1 分。
  • 5 ∼ 12 5\sim 12 512 0 0 0 分。

求得分最多的队伍的分数。

输入格式

两个整数 n , x 1 n,x_1 n,x1 n n n 为球队数, x 1 x_1 x1 为第一次胜队号,第 i ( i ≥ 2 ) i(i\ge2) i(i2) 场比赛胜队的编号由
以下公式确定:

x i = ( ( x i − 1 × 3703 + 1047 )   m o d   n ) + 1 x_i = ((x_{i-1}\times 3703+1047) \bmod n)+1 xi=((xi1×3703+1047)modn)+1

输出格式

一个整数,即得分最多队的分数。

样例 #1

样例输入 #1

10 5

样例输出 #1

3

提示

1 ≤ x 1 ≤ n ≤ 1 0 6 1\le x_1\le n\le10^6 1x1n106

思路

按照题目要求模拟。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n;
int a[1000010],sum[1000010];

void solve()
{
	cin >> n >> a[1];
	for (int i = 2;i <= n;i++)
		a[i] = ((a[i-1]*3703+1047)%n) + 1;
	int now = 0;
	for (int i = 1;i <= n;i++)
	{
		if (a[i] == a[i-1])
			now++;
		else
			now = 1;
		if (now >= 3)
			sum[a[i]] += 3;
		else
			sum[a[i]] += now;
	}
	int mx = 0;
	for (int i = 1;i <= n;i++)
		mx = max(mx,sum[i]);
	cout << mx; 
}

signed main()
{
	solve();
	return 0;
}

[信息与未来 2015] 求回文数

题目描述

一个正整数,正读和反读都相同的数为回文数,例如 22 , 131 , 2442 , 37073 , 6 , ⋯ 22,131,2442,37073,6,\cdots 22,131,2442,37073,6,。所有的 1 1 1 位数都是回文数。

现给出一个正整数 n n n,求出 [ 1 , n ] [1,n] [1,n] 中的回文数的个数。

输入格式

一个整数 n n n

输出格式

一个整数,即 1 ∼ n 1\sim n 1n 中全部回文数的个数。

样例 #1

样例输入 #1

24

样例输出 #1

11

提示

样例解释

1 1 1 24 24 24 中,回文数有 1 ∼ 9 , 11 , 22 1\sim 9,11,22 19,11,22,共 11 11 11 个。

数据范围

1 ≤ n ≤ 1 0 4 1\le n\le10^4 1n104

思路

枚举。从 1 1 1 枚举到 n n n,然后判断是否为回文数。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int n;
int sum;

bool judge(int x)
{
	int y = x,numa = 0;
	while (y)
		numa = numa*10+y%10,y /= 10;
	if (numa == x)
		return true;
	return false;
}

void solve()
{
	cin >> n;
	for (int i = 1;i <= n;i++)
		if (judge(i))
			sum++;
	cout << sum;
}

signed main()
{
	solve();
	return 0;
}

[信息与未来 2015] 连续数的和

题目描述

给出两个整数 n n n k k k,求出 1 ∼ n 1\sim n 1n 中连续 k k k 个数的和为完全平方数的个数。

输入格式

一行两个整数 n , k n,k n,k

输出格式

一行一个整数,即 1 ∼ n 1\sim n 1n 中连续 k k k 个数的和为平方数的个数。

样例 #1

样例输入 #1

10 3

样例输出 #1

1

提示

样例解释

1 ∼ 10 1\sim10 110 中,连续 3 3 3 个数的和有:

  • 1 + 2 + 3 = 6 1+2+3=6 1+2+3=6
  • 2 + 3 + 4 = 9 = 3 2 2+3+4=9=3^2 2+3+4=9=32
  • 3 + 4 + 5 = 12 3+4+5=12 3+4+5=12
  • 4 + 5 + 6 = 15 4+5+6=15 4+5+6=15
  • 5 + 6 + 7 = 18 5+6+7=18 5+6+7=18
  • 6 + 7 + 8 = 21 6+7+8=21 6+7+8=21
  • 7 + 8 + 9 = 24 7+8+9=24 7+8+9=24
  • 8 + 9 + 10 = 27 8+9+10=27 8+9+10=27

故只有 1 1 1 个。

数据范围

2 ≤ n ≤ 7 × 1 0 4 , 1 ≤ k ≤ n 2\le n\le 7\times 10^4,1\le k\le n 2n7×104,1kn

思路

枚举所有情况,判断是否为平方数。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

void solve()
{
	int n,k;
	cin >> n >> k;
	int now = (1+k)*k/2,sum = 0;
	for (int i = k;i <= n;i++)
	{
		if ((int)(sqrt(now))*(int)(sqrt(now)) == now)
			sum++;
		now -= (i-k+1);
		now += i+1;
	}
	cout << sum;
}

signed main()
{
	solve();
	return 0;
}

[信息与未来 2015] 夏令营小旗手

题目描述

2015 2015 2015 年江苏省“信息与未来”小学夏令营在洪泽县实验小学进行,组委会决定在洪泽实验小学的学生中挑选一名小旗手,推选方法如下:

洪泽实验小学有 n n n 名学生,每名学生有一个学号,学号为 1 ∼ n 1\sim n 1n。同时,每名同学有一张选票,可以推选一名同学为小旗手,最后,得票最多者当选;若得票最有多名(票数相同),则学号小者当选。

例如 n = 8 n=8 n=8,选票为 2 , 3 , 4 , 4 , 3 , 4 , 1 , 6 2,3,4,4,3,4,1,6 2,3,4,4,3,4,1,6 4 4 4 号学生得票最多( 3 3 3 票),当选小旗手。

输入格式

两个整数 n , x 1 n,x_1 n,x1 n n n 为学生数, x 1 x_1 x1 为第一个选票上的学号,之后的选票 x i ( i ≥ 2 ) x_i(i\ge2) xi(i2) 由下面的递推关系给出:

x i = ( ( x i − 1 × 37 + 33031 )   m o d   n ) + 1 x_i = ((x_{i-1}\times 37+33031)\bmod n)+1 xi=((xi1×37+33031)modn)+1

其中   m o d   \bmod mod 为取余运算。例如, 13   m o d   8 = 5 , 21   m o d   21 = 0 13 \bmod 8 = 5,21 \bmod 21 = 0 13mod8=5,21mod21=0。根据这个公式,就能从 x 1 x_1 x1 推出 x 2 ∼ n x_{2\sim n} x2n

输出格式

一个整数,即选出的小旗手的学号。

样例 #1

样例输入 #1

5 2

样例输出 #1

2

提示

样例解释

x = { 2 , 1 , 4 , 5 , 2 } x=\{2,1,4,5,2\} x={2,1,4,5,2} 2 2 2 号选手票数最多。

数据范围

1 ≤ x 1 ≤ n ≤ 1 0 3 1\le x_1\le n\le10^3 1x1n103

思路

先算出每个人的投票,然后用 vis 记录求出最大值。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

int vis[1010];

void solve()
{
	int n,m;
	cin >> n >> m;
	vis[m]++;
	for (int i = 2;i <= n;i++)
	{
		m = ((m*37 + 33031)%n) + 1;
		vis[m]++;
	}
	int mx = 0,pos = 0;
	for (int i = 1;i <= n;i++)
		if (mx < vis[i])
		{
			mx = vis[i];
			pos = i;
		}
	cout << pos;
}

signed main()
{
	solve();
	return 0;
}
  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值