[信息与未来 2015] 加数
题目描述
给出一个正整数 nnn,在 nnn 的右边加入 ⌊n2⌋\left\lfloor\dfrac n2\right\rfloor⌊2n⌋,然后在新数的右边
再加入 ⌊⌊n2⌋2⌋\left\lfloor\dfrac{\left\lfloor\dfrac n2\right\rfloor}2\right\rfloor2⌊2n⌋,一直这样进行下去,直到加入的数为 000 为止(注意,000 不应当被加入)。
求加数结束后新数的长度。
输入格式
一行一个整数 nnn。
输出格式
一行一个整数,为加数结束后新数的长度。
样例 #1
样例输入 #1
37
样例输出 #1
8
提示
样例解释
- ⌊372⌋=18\left\lfloor\dfrac{37}2\right\rfloor=18⌊237⌋=18,加到 nnn 的右边成为 371837183718;
- ⌊182⌋=9\left\lfloor\dfrac{18}2\right\rfloor=9⌊218⌋=9,加到新数的右边成为 371893718937189;
- ⌊92⌋=4\left\lfloor\dfrac{9}2\right\rfloor=4⌊29⌋=4,加到新数的右边成为 371894371894371894;
- ⌊42⌋=2\left\lfloor\dfrac{4}2\right\rfloor=2⌊24⌋=2,加到新数的右边成为 371894237189423718942;
- ⌊22⌋=1\left\lfloor\dfrac{2}2\right\rfloor=1⌊22⌋=1,加到新数的右边成为 371894213718942137189421;
- ⌊12⌋=0\left\lfloor\dfrac12\right\rfloor=0⌊21⌋=0,加数结束,最后得到的数是一个 888 位数。
数据范围
1≤n≤1051\le n\le10^51≤n≤105。
思路
直接模拟,判断位数。
代码
#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] 中间值
题目描述
给出一个正整数 nnn,生成长度为 nnn 的数列 aaa,其中 ai=i(1≤i≤n)a_i=i(1\le i\le n)ai=i(1≤i≤n)。
- 若 nnn 为奇数,则输出 aaa 的中间数(位于 aaa 正中位置的数);
- 若 nnn 为偶数,则输出位于 aaa 中间两个数的和。
输入格式
一个正整数 nnn。
输出格式
一个正整数。若 nnn 为奇数,则输出其中间值;若 nnn 为偶数,则输出两个中间值的和。
样例 #1
样例输入 #1
9
样例输出 #1
5
样例 #2
样例输入 #2
10
样例输出 #2
11
提示
1≤n≤10181\le n\le10^{18}1≤n≤1018。
思路
若 nnn 为奇数,则答案为 n÷2+1n\div2+1n÷2+1;
若 nnn 为偶数,则答案为 n+1n+1n+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] 买木头
题目描述
有 nnn 个木材供应商,每个供应商有长度相同的一定数量的木头。长木头可以锯短,但短木头不能接长。有一个客人要求 mmm 根长度相同的木头,要求计算出:此时供货商提供的木头满足客人要求的最大长度是多少。
例如 n=2,m=30n=2,m=30n=2,m=30,两个供货商的木头为:
- 12,1012,1012,10(第 111 个供货商的木头长度为 121212,共有 101010 根);
- 5,105,105,10(第 222 个供货商的木头长度为 555,共有 101010 根)。
计算的结果为 555,即长度为 121212 的木头一根可锯出两根长度为 555 的木头,多余的无用;长度为 555 的木头不动,此时,可以得到 303030 根长度为 555 的木头。
输入格式
一行四个整数 n,m,l1,s1n,m,l_1,s_1n,m,l1,s1。其中 l1l_1l1 是第一个供货商木头的长度,s1s_1s1 是第一个供货商木头的数量。其他供货商木头
的长度和数量 lil_ili 和 si(i≥2)s_i(i\ge2)si(i≥2)由下面的公式给出:
- li=((li−1×37011+10193) mod 10000)+1l_i=((l_{i-1}\times37011+10193) \bmod 10000)+1li=((li−1×37011+10193)mod10000)+1;
- si=((si−1×73011+24793) mod 100)+1s_i=((s_{i-1}\times73011+24793) \bmod 100)+1si=((si−1×73011+24793)mod100)+1。
输出格式
一个整数,即满足要求的 mmm 根长度相同的木头的最大长度。
样例 #1
样例输入 #1
10 10000 8 20
样例输出 #1
201
提示
1≤n≤104,1≤m≤106,1≤l1≤104,1≤s1≤1001\le n\le10^4,1\le m\le10^6,1\le l_1\le10^4, 1\le s_1\le1001≤n≤104,1≤m≤106,1≤l1≤104,1≤s1≤100。
思路
二分木头的长度,每次 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] 拴奶牛
题目描述
有 nnn 头奶牛,有 kkk 个木桩,每个木桩有一个位置,一个木桩上只能拴一头奶牛。由于奶牛好斗,所以在拴奶牛的时候,要求距离最近的奶牛的距离尽可能大。
例如 n=4,k=6n=4,k=6n=4,k=6,木桩的位置为 0,3,4,7,8,90,3,4,7,8,90,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,90,3,4,90,3,4,9:此时最近距离为 111(3,43,43,4 之间);
- 0,3,7,90,3,7,90,3,7,9:此时最近距离为 222。
输入格式
三个整数 n,k,p1n,k,p_1n,k,p1,其中 p1p_1p1 为第 111 个木桩的位置,其他木桩 pi(i≥2)p_i(i\ge2)pi(i≥2) 的位置由下面公式给出:
pi=pi−1+((pi−1×2357+137) mod 10)+1p_i = p_{i-1} + ((p_{i-1}\times2357+137) \bmod 10)+1pi=pi−1+((pi−1×2357+137)mod10)+1。
输出格式
一个整数,即奶牛间最近距离的最大值。
样例 #1
样例输入 #1
25 70 99
样例输出 #1
12
提示
1≤n≤k≤106,0≤p1≤1001\le n\le k\le10^6,0\le p_1\le1001≤n≤k≤106,0≤p1≤100。
思路
二分两只牛之间的距离,每次 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] 分数计数
题目描述
有 nnn 个球队,编号为 1∼n1\sim n1∼n,共进行 nnn 场比赛,每场比赛有一个胜队。计分方法如下:
- 是连胜中的第一次胜利,则本次胜利得 111 分。
- 是连胜中的第二次胜利,则本次胜利得 222 分。
- 是连胜中的第三次胜利,则本次胜利得 333 分。
- 连胜超过三次以上的胜场,每场得 333 分。
例如 n=12n=12n=12,比赛的胜队为 1,2,1,1,3,2,1,1,1,1,4,21,2,1,1,3,2,1,1,1,1,4,21,2,1,1,3,2,1,1,1,1,4,2,计分如下:
- 队 111:1+1+2+1+2+3+3=131+1+2+1+2+3+3=131+1+2+1+2+3+3=13 分;
- 队 222:1+1+1=31+1+1=31+1+1=3 分;
- 队 3∼43\sim 43∼4:111 分。
- 队 5∼125\sim 125∼12:000 分。
求得分最多的队伍的分数。
输入格式
两个整数 n,x1n,x_1n,x1,nnn 为球队数,x1x_1x1 为第一次胜队号,第 i(i≥2)i(i\ge2)i(i≥2) 场比赛胜队的编号由
以下公式确定:
xi=((xi−1×3703+1047) mod n)+1x_i = ((x_{i-1}\times 3703+1047) \bmod n)+1xi=((xi−1×3703+1047)modn)+1。
输出格式
一个整数,即得分最多队的分数。
样例 #1
样例输入 #1
10 5
样例输出 #1
3
提示
1≤x1≤n≤1061\le x_1\le n\le10^61≤x1≤n≤106。
思路
按照题目要求模拟。
代码
#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,\cdots22,131,2442,37073,6,⋯。所有的 111 位数都是回文数。
现给出一个正整数 nnn,求出 [1,n][1,n][1,n] 中的回文数的个数。
输入格式
一个整数 nnn。
输出格式
一个整数,即 1∼n1\sim n1∼n 中全部回文数的个数。
样例 #1
样例输入 #1
24
样例输出 #1
11
提示
样例解释
在 111 至 242424 中,回文数有 1∼9,11,221\sim 9,11,221∼9,11,22,共 111111 个。
数据范围
1≤n≤1041\le n\le10^41≤n≤104。
思路
枚举。从 111 枚举到 nnn,然后判断是否为回文数。
代码
#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] 连续数的和
题目描述
给出两个整数 nnn 和 kkk,求出 1∼n1\sim n1∼n 中连续 kkk 个数的和为完全平方数的个数。
输入格式
一行两个整数 n,kn,kn,k。
输出格式
一行一个整数,即 1∼n1\sim n1∼n 中连续 kkk 个数的和为平方数的个数。
样例 #1
样例输入 #1
10 3
样例输出 #1
1
提示
样例解释
在 1∼101\sim101∼10 中,连续 333 个数的和有:
- 1+2+3=61+2+3=61+2+3=6;
- 2+3+4=9=322+3+4=9=3^22+3+4=9=32;
- 3+4+5=123+4+5=123+4+5=12;
- 4+5+6=154+5+6=154+5+6=15;
- 5+6+7=185+6+7=185+6+7=18;
- 6+7+8=216+7+8=216+7+8=21;
- 7+8+9=247+8+9=247+8+9=24;
- 8+9+10=278+9+10=278+9+10=27。
故只有 111 个。
数据范围
2≤n≤7×104,1≤k≤n2\le n\le 7\times 10^4,1\le k\le n2≤n≤7×104,1≤k≤n。
思路
枚举所有情况,判断是否为平方数。
代码
#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] 夏令营小旗手
题目描述
201520152015 年江苏省“信息与未来”小学夏令营在洪泽县实验小学进行,组委会决定在洪泽实验小学的学生中挑选一名小旗手,推选方法如下:
洪泽实验小学有 nnn 名学生,每名学生有一个学号,学号为 1∼n1\sim n1∼n。同时,每名同学有一张选票,可以推选一名同学为小旗手,最后,得票最多者当选;若得票最有多名(票数相同),则学号小者当选。
例如 n=8n=8n=8,选票为 2,3,4,4,3,4,1,62,3,4,4,3,4,1,62,3,4,4,3,4,1,6,444 号学生得票最多(333 票),当选小旗手。
输入格式
两个整数 n,x1n,x_1n,x1,nnn 为学生数,x1x_1x1 为第一个选票上的学号,之后的选票 xi(i≥2)x_i(i\ge2)xi(i≥2) 由下面的递推关系给出:
xi=((xi−1×37+33031) mod n)+1x_i = ((x_{i-1}\times 37+33031)\bmod n)+1xi=((xi−1×37+33031)modn)+1。
其中 mod \bmodmod 为取余运算。例如,13 mod 8=5,21 mod 21=013 \bmod 8 = 5,21 \bmod 21 = 013mod8=5,21mod21=0。根据这个公式,就能从 x1x_1x1 推出 x2∼nx_{2\sim n}x2∼n。
输出格式
一个整数,即选出的小旗手的学号。
样例 #1
样例输入 #1
5 2
样例输出 #1
2
提示
样例解释
x={2,1,4,5,2}x=\{2,1,4,5,2\}x={2,1,4,5,2},222 号选手票数最多。
数据范围
1≤x1≤n≤1031\le x_1\le n\le10^31≤x1≤n≤103。
思路
先算出每个人的投票,然后用 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;
}
763

被折叠的 条评论
为什么被折叠?



