C - Black Box
ADD (x): put element x into Black Box;
GET: increase i by 1 and give an i-minimum out of all integers containing in the Black Box. Keep in mind that i-minimum is a number located at i-th place after Black Box elements sorting by non- descending.
Let us examine a possible sequence of 11 transactions:
Example 1
N Transaction i Black Box contents after transaction Answer
(elements are arranged by non-descending)
1 ADD(3) 0 3
2 GET 1 3 3
3 ADD(1) 1 1, 3
4 GET 2 1, 3 3
5 ADD(-4) 2 -4, 1, 3
6 ADD(2) 2 -4, 1, 2, 3
7 ADD(8) 2 -4, 1, 2, 3, 8
8 ADD(-1000) 2 -1000, -4, 1, 2, 3, 8
9 GET 3 -1000, -4, 1, 2, 3, 8 1
10 GET 4 -1000, -4, 1, 2, 3, 8 2
11 ADD(2) 4 -1000, -4, 1, 2, 2, 3, 8
It is required to work out an efficient algorithm which treats a given sequence of transactions. The maximum number of ADD and GET transactions: 30000 of each type.
Let us describe the sequence of transactions by two integer arrays:
1. A(1), A(2), ..., A(M): a sequence of elements which are being included into Black Box. A values are integers not exceeding 2 000 000 000 by their absolute value, M <= 30000. For the Example we have A=(3, 1, -4, 2, 8, -1000, 2).
2. u(1), u(2), ..., u(N): a sequence setting a number of elements which are being included into Black Box at the moment of first, second, ... and N-transaction GET. For the Example we have u=(1, 2, 6, 6).
The Black Box algorithm supposes that natural number sequence u(1), u(2), ..., u(N) is sorted in non-descending order, N <= M and for each p (1 <= p <= N) an inequality p <= u(p) <= M is valid. It follows from the fact that for the p-element of our u sequence we perform a GET transaction giving p-minimum number from our A(1), A(2), ..., A(u(p)) sequence.
7 4
3 1 -4 2 8 -1000 2
1 2 6 6
3
3
1
2
一开始用 set 模拟,WA了,因为相同的数不能插入两次。后改用优先队列A了,方法大致如下:设上一时刻输出的值为 t ,则用一个最小值优先的队列存大于 t 的值,用一个最大值优先的队列存小于等于 t 的值,通过调整两个队列中的元素找出要求值。
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 30000 + 5;
int a[maxn],u[maxn];
int n,m;
priority_queue<int,vector<int>,greater<int> > s1;
priority_queue<int,vector<int>,less<int> >s2;
int main()
{
int t,q,l,r,p;
q = 1,p = 0;
scanf("%d %d",&m,&n);
for(int i = 1;i <= m; ++i) scanf("%d",&a[i]);
for(int i = 1;i <= n; ++i) scanf("%d",&u[i]);
for(int i = 1;i <= m; ++i)
{
if(a[i] > p) s1.push(a[i]);
else s2.push(a[i]);
while(i == u[q] && q <= n)
{
l = s2.size(),r = s1.size();
if(q < l)
{
for(int j = l;j > q; --j)
{
t = s2.top(),s2.pop();
s1.push(t);
}
}
else if(q > l)
{
for(int j = l;j < q; ++j)
{
t = s1.top(),s1.pop();
s2.push(t);
}
}
p = s2.top();
printf("%d\n",p);
++q;
}
}
return 0;
}
D - Leading Trailing
You are given two integers: n and k, your task is to find the most significant three digits, and least significant three digits ofnk.
Input starts with an integer T (≤ 1000), denoting the number of test cases.
Each case starts with a line containing two integers: n (2 ≤ n < 231) andk (1 ≤ k ≤ 107).
For each case, print the case number and the three leading digits (most significant) and three trailing digits (least significant). You can assume that the input is given such thatnk contains at least six digits.
5
123456 1
123456 2
2 31
2 32
29 8751919
Case 1: 123 456
Case 2: 152 936
Case 3: 214 648
Case 4: 429 296
Case 5: 665 669
后三位快速幂取模即可,这里简单说一下前三位取法,可以使用对数,log10 ( n ^ k ) = k log10 ( n ) ,设结果的整数部分为 a ,小数部分为 b 。则 10 ^ b 确定 n ^ k 的尾数。b =(double)k log10 ( n ) - (int)k log10 ( n ) 。结果取 10^ b 的前三位即可。
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int fastpow(int a,int b,int c)
{
int s = 1;
a %= c;
while(b > 0)
{
if(b&1) s = s * a % c;
a = a * a % c;
b >>= 1;
}
return s;
}
int main()
{
int n,k,t,p,pp,T;
int a[6];
scanf("%d",&T);
pp = T;
while(T--)
{
scanf("%d %d",&n,&k);
double x = (double)k * log10(n) - (int)(k * log10(n));
a[0] = (int)(pow(10,x) * 100);
int t = fastpow(n,k,1000),p = 100;
for(int i = 1;i < 4; ++i)
{
a[i] = t / p;
t %= p;
p /= 10;
}
printf("Case %d: ",pp - T);
for(int i = 0;i < 4; ++i)
{
if(i == 1) printf(" ");
printf("%d",a[i]);
}
printf("\n");
}
return 0;
}
E - Aladdin and the Flying Carpet
It's said that Aladdin had to solve seven mysteries before getting the Magical Lamp which summons a powerful Genie. Here we are concerned about the first mystery.
Aladdin was about to enter to a magical cave, led by the evil sorcerer who disguised himself as Aladdin's uncle, found a strange magical flying carpet at the entrance. There were some strange creatures guarding the entrance of the cave. Aladdin could run, but he knew that there was a high chance of getting caught. So, he decided to use the magical flying carpet. The carpet was rectangular shaped, but not square shaped. Aladdin took the carpet and with the help of it he passed the entrance.
Now you are given the area of the carpet and the length of the minimum possible side of the carpet, your task is to find how many types of carpets are possible. For example, the area of the carpet 12, and the minimum possible side of the carpet is 2, then there can be two types of carpets and their sides are: {2, 6} and {3, 4}.
Input starts with an integer T (≤ 4000), denoting the number of test cases.
Each case starts with a line containing two integers: a b (1 ≤ b ≤ a ≤ 1012) wherea denotes the area of the carpet and b denotes the minimum possible side of the carpet.
For each case, print the case number and the number of possible carpets.
2
10 2
12 2
Case 1: 1
Case 2: 2
唯一分解定理的运用。求出 a 的所有因子个数,除二便是边的对数。暴力出小于 b 的所有对数,跟前面的减一下就得到了。数据最大是 1e12,素数表打到 1e6 即可,因为大于 1e6 的因子最多有1个,所以除掉所有小于 1e6 的因子后判断一下剩下的部分是否大于 1 即可知道是否有大于 1e7 的因子。
虽然过了但是差点超了时限,dalao说是常数太大,后续再改进吧。。。
#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e6 + 5;
bool p[maxn];
int c[maxn];
void Getprime()
{
memset(p,false,sizeof(p));
int m = sqrt(maxn + 0.5);
for(int i = 2;i <= m; ++i)
{
if(!p[i])
for(int j = i * i;j <= maxn; j += i) p[j] = true;
}
}
int main()
{
Getprime();
int j = 0,sum;
for(int i = 2;i <= maxn; ++i) if(!p[i]) c[j++] = i;
int t,pp;
long long a,b;
scanf("%d",&t);
pp = t;
while(t--)
{
sum = 1;
scanf("%lld %lld",&a,&b);
long long te = a;
if(b * b > a) sum = 0;
else
{
for(int i = 0;i < j && te > 1; ++i)
{
if(te % c[i] == 0)
{
int mark = 1;
while(te % c[i] == 0 && te > 1)
{
te /= c[i];
++mark;
}
sum = sum * mark;
}
}
if(te > 1) sum <<= 1;
sum >>= 1;
for(int i = 1;i < b; ++i) if(a % i == 0) --sum;
}
printf("Case %d: %d\n",pp - t,sum);
}
return 0;
}
L - Bi-shoe and Phi-shoe
Bamboo Pole-vault is a massively popular sport in Xzhiland. And Master Phi-shoe is a very popular coach for his success. He needs some bamboos for his students, so he asked his assistant Bi-Shoe to go to the market and buy them. Plenty of Bamboos of all possible integer lengths (yes!) are available in the market. According to Xzhila tradition,
Score of a bamboo = Φ (bamboo's length)
(Xzhilans are really fond of number theory). For your information, Φ (n) = numbers less thann which are relatively prime (having no common divisor other than 1) ton. So, score of a bamboo of length 9 is 6 as 1, 2, 4, 5, 7, 8 are relatively prime to 9.
The assistant Bi-shoe has to buy one bamboo for each student. As a twist, each pole-vault student of Phi-shoe has a lucky number. Bi-shoe wants to buy bamboos such that each of them gets a bamboo with a score greater than or equal to his/her lucky number. Bi-shoe wants to minimize the total amount of money spent for buying the bamboos. One unit of bamboo costs 1 Xukha. Help him.
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case starts with a line containing an integer n (1 ≤ n ≤ 10000) denoting the number of students of Phi-shoe. The next line containsn space separated integers denoting the lucky numbers for the students. Each lucky number will lie in the range[1, 106].
For each case, print the case number and the minimum possible money spent for buying the bamboos. See the samples for details.
3
5
1 2 3 4 5
6
10 11 12 13 14 15
2
1 1
Case 1: 22 Xukha
Case 2: 88 Xukha
Case 3: 4 Xukha
题目大意:一个数的价值(value)被定义为小于它的并与它互质的数的个数,给定一系列数(lucky number),对于每个 lucky number 找到一个 value 大于它的最小的数,求这些数的和。
#include<algorithm>
#include<set>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 1e6 * 2;
bool p[maxn];
void Getprime()
{
memset(p,false,sizeof(p));
int m = sqrt(maxn + 0.5);
for(int i = 2;i <= m; ++i)
{
if(!p[i]) for(int j = i * i;j <= maxn; j += i) p[j] = true;
}
}
set<int> s;
int main()
{
Getprime();
int t,n,pp,x;
long long sum;
for(int i = 2;i <= maxn; ++i) if(!p[i]) s.insert(i - 1);
scanf("%d",&t);
pp = t;
while(t--)
{
sum = 0;
scanf("%d",&n);
for(int i = 0;i < n; ++i)
{
scanf("%d",&x);
set<int>::iterator it;
it = s.lower_bound(x);
sum += (*(it) + 1);
}
printf("Case %d: %lld Xukha\n",pp - t,sum);
}
return 0;
}