公元年在第几个世纪中?
一个世纪是由个年份组成的一个区间。如,世纪为年,世纪为年,……
将答案输出为一个整数。
输出 | |
---|---|
根据本题条件我们可以推出:公元年在世纪。
#include <cstdio>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
printf("%d\n", n % 100 == 0? n / 100: n / 100 + 1);
return 0;
}
对于整数,执行次如下操作:
输出最终的。
输出 | ||
---|---|---|
本题我们按照题意模拟即可,但我们需要证明答案不会超过,这样才能使用long long
:
00
结尾,就证明了它是的倍数。#include <cstdio>
using namespace std;
int main()
{
long long n;
int k;
scanf("%lld%d", &n, &k);
while(k--)
n = n % 200LL == 0LL? n / 200LL: n * 1000LL + 200LL;
printf("%lld\n", n);
return 0;
}
给定序列,找到符合下列条件的所有:
输出 | |
---|---|
首先,最容易想到的的暴力算法肯定不行,因为。
我们考虑用桶优化:
我们有个桶,分别如下:
桶的编号 | 元素 | 元素 | 元素 | 元素 | …… | 元素除以的余数 |
---|---|---|---|---|---|---|
…… | ||||||
…… | ||||||
…… | ||||||
…… | …… | …… | …… | …… | …… | …… |
…… | ||||||
…… | ||||||
这时,我们发现,每个桶中的每个元素都能与这个同种的其他元素组成一对,所以我们只要在将元素加入桶中前将答案加上桶目前的大小即可。 |
总时间复杂度。
我们的桶中不需要真正的元素,只需要记录桶的大小即可。
注意:答案的数据类型一定要用long long
!
#include <cstdio>
#define MOD 200
using namespace std;
int cnt[MOD];
int main()
{
int n;
scanf("%d", &n);
long long ans = 0LL;
while(n--)
{
int x;
scanf("%d", &x);
ans += cnt[x %= MOD] ++;
}
printf("%lld\n", ans);
return 0;
}
给定序列。你要从中选出两个子序列和(下标不同,不要求连续),使得。
如果没有合法的和,输出No
。
如果有合法的和,按下列格式输出,其中为的长度、为的长度,为中元素对应的下标,为中元素对应的下标:
略,请自行前往AtCoder查看
我们可以证明,只要,那么就一定有解。证明如下:
当时,我们暴力枚举所有可能;
当时,我们暴力枚举其中任意个元素组成的所有可能即可找到解。
#include <cstdio>
#include <vector>
#define maxn 10
#define MOD 200
using namespace std;
int a[maxn];
vector<int> bkt[MOD];
inline void print(const vector<int>& v)
{
printf("%llu", v.size());
for(int x: v)
printf(" %d", x + 1);
putchar('\n');
}
int main()
{
int n;
scanf("%d", &n);
if(n > 8) n = 8;
for(int i=0; i<n; i++)
scanf("%d", a + i);
int lim = 1 << n;
for(int st=0; st<lim; st++)
{
int s = 0;
vector<int> pos;
for(int i=0; i<n; i++)
if(st >> i & 1)
s = (s + a[i]) % MOD, pos.push_back(i);
if(!bkt[s].empty())
{
puts("Yes");
print(bkt[s]);
print(pos);
return 0;
}
else bkt[s] = pos;
}
puts("No");
return 0;
}
有个三元组(),按如下排序:
求第个。
输出第个,用空格分隔。
输出 | ||
---|---|---|
由于每个三元组的和都不会超过,所以我们考虑暴力枚举三元组的和,这样就能快速算出第个三元组的和。那么,问题来了:符合的三元组(均不超过)有多少个?
这可以用容斥原理解决。首先,我们发现,上述问题实际上就是在求如下方程解的个数:
如果我们将问题改成求如下方程解的个数(注意和的区别):
这个可以用挡板法解决,在个位置上任选个插入挡板,挡板分开的就是,则公式为。我们设上述方程解的个数(),则总方程解的个数为。
我们考虑一个、两个(不可能有三个)数大于的情况,这样这个方程解的个数就为。
计算时注意特判的情况,否则可能会出现负数!
#include <cstdio>
using namespace std;
using LL = long long;
int n;
inline int max(int x, int y) { return x > y? x: y; }
inline int min(int x, int y) { return x < y? x: y; }
inline LL f(LL n) { return n-- > 2? n * (n - 1LL) >> 1LL: 0LL; }
inline LL count(int s) { return f(s) - 3 * (f(s - n) - f(s - (n << 1))); }
int main()
{
LL k;
scanf("%d%lld", &n, &k);
int lim = n * 3;
for(int sum=3; sum<=lim; sum++)
{
LL cnt = count(sum);
if(k > cnt) { k -= cnt; continue; }
for(int a=1; a<=n; a++)
{
int minb = max(1, sum - a - n), maxb = min(n, sum - a - 1);
if(minb > maxb) continue;
int num = maxb - minb + 1;
if(k <= num)
{
int b = minb + k - 1;
int c = sum - a - b;
printf("%d %d %d\n", a, b, c);
return 0;
}
k -= num;
}
}
return 0;
}