Codeforces Round #536 (Div. 2)【己亥年农历新年赛】简略题解
【题目地址】
写在前面
$\ \ \ \ \ \ \,$这场比赛是wc2019回家那天晚上举办的,从8点到10点刚好在动车上,饥寒交迫,还拉肚子(吃不惯粤菜),就没有参加,是后面写的。
$\ \ \ \ \ \ \,$这套题在洛谷上面五颜六色的,很有意思啊(除了没有红的),题目也算可做,感觉很过年很快乐呢(嘤嘤
A. Lunar New Year and Cross Counting
$\ \ \ \ \ \ \,$模拟?暴力?可以不解释吗……
1 |
|
B. Lunar New Year and Food Ordering
$\ \ \ \ \ \ \,$这个也是模拟吧,我们把菜品排个序,用一个指针跳就好了吧……(敷衍1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using namespace std;
const int inf=0x7fffffff;
const double eps=1e-10;
const double pi=acos(-1.0);
//char buf[1<<15],*S=buf,*T=buf;
//char getch(){return S==T&&(T=(S=buf)+fread(buf,1,1<<15,stdin),S==T)?0:*S++;}
inline int read(){
int x=0,f=1;char ch;ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=0;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch&15);ch=getchar();}
if(f)return x;else return -x;
}
const int N=1e5+10;
int n,m,z=1;
int rk[N];
struct node{int a,c,id;}di[N];
inline bool operator <(const node &a,const node &b)
{return a.c<b.c||(a.c==b.c&&a.id<b.id);}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)di[i].a=read();
for(int i=1;i<=n;i++)di[i].c=read();
for(int i=1;i<=n;i++)di[i].id=i;
sort(di+1,di+n+1);
for(int i=1;i<=n;i++)rk[di[i].id]=i;
while(m--){
int kind=read(),cnt=read();
if(di[rk[kind]].a>=cnt){
di[rk[kind]].a-=cnt;
printf("%lld\n",1ll*di[rk[kind]].c*cnt);
continue;
}
long long ls=0ll;
if(di[rk[kind]].a){
cnt-=di[rk[kind]].a;
ls+=1ll*di[rk[kind]].c*di[rk[kind]].a;
di[rk[kind]].a=0;
}
while(cnt){
if((!di[z].a)&&z<=n)z++;
if(z>n){ls=0;break;}
else{
if(di[z].a>=cnt){
di[z].a-=cnt;
ls+=1ll*di[z].c*cnt;
cnt=0;
}
else{
cnt-=di[z].a;
ls+=1ll*di[z].c*di[z].a;
di[z].a=0;
}
}
}
printf("%lld\n",ls);
}
return 0;
}
C. Lunar New Year and Number Division
$\ \ \ \ \ \ \,$根据二项式定理,当然是两个两个分为一组最合算了($n$ 范围明示
$\ \ \ \ \ \ \,$我们展开可得:
$(a+b)^2=a^2+b^2+2ab$
$\ \ \ \ \ \ \,$那么我们就想要两个成积较小的分一组最好,就是排序过后,最小的和最大的分一组好了呀。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using namespace std;
const int inf=0x7fffffff;
const double eps=1e-10;
const double pi=acos(-1.0);
//char buf[1<<15],*S=buf,*T=buf;
//char getch(){return S==T&&(T=(S=buf)+fread(buf,1,1<<15,stdin),S==T)?0:*S++;}
inline int read(){
int x=0,f=1;char ch;ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=0;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch&15);ch=getchar();}
if(f)return x;else return -x;
}
const int N=3e5+10;
long long ans;
int a[N],n;
int main()
{
n=read();
for(int i=1;i<=n;i++)a[i]=read();
sort(a+1,a+n+1);
for(int i=1,j=n;i<=j;i++,j--)
ans+=1ll*(a[i]+a[j])*(a[i]+a[j]);
printf("%lld\n",ans);
return 0;
}
D. Lunar New Year and a Wander
$\ \ \ \ \ \ \,$BFS……
$\ \ \ \ \ \ \,$并不是,其实也差不多吧,当前可以走到的点,我们把他放进堆里面,然后每次走堆里最小的这个样子。
$\ \ \ \ \ \ \,$(因为题意没看懂翻车了几次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using namespace std;
const int inf=0x7fffffff;
const double eps=1e-10;
const double pi=acos(-1.0);
//char buf[1<<15],*S=buf,*T=buf;
//char getch(){return S==T&&(T=(S=buf)+fread(buf,1,1<<15,stdin),S==T)?0:*S++;}
inline int read(){
int x=0,f=1;char ch;ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=0;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch&15);ch=getchar();}
if(f)return x;else return -x;
}
const int N=1e5+10;
int n,m;
bool used[N];
vector<int> G[N];
priority_queue<int> Q;
int main()
{
n=read();m=read();
while(m--){
int a=read(),b=read();
G[a].push_back(b);
G[b].push_back(a);
}
for(int i=1;i<=n;i++)
sort(G[i].begin(),G[i].end());
Q.push(-1);used[1]=1;
while(!Q.empty()){
int u=-Q.top();Q.pop();
printf("%d ",u);
for(auto v:G[u])if(!used[v])
Q.push(-v),used[v]=1;
}
return 0;
}
E. Lunar New Year and Red Envelopes
$\ \ \ \ \ \ \,$后面两道题就开始有讲的意思了,反正这道题我并没有独自写出来(我怀疑题都没有怎么读懂(我好菜呀
$\ \ \ \ \ \ \,$题目做法是DP,我们定义$f_{i,j}$,表示被打扰了 $i$ 次,现在时间是 $j$ 的最小收益。转移方程呢就是:
$f_{i,j+1}=f_{i-1,j}$
$f_{i,a_l.d+1}=f_{i-1,k}+a_l.w$
$\ \ \ \ \ \ \,$我们预处理数当前时间用那个红包好,就可以降低复杂度到$O(nm)$,具体来说,就是哪个钱多哪个好,钱一样多的话就是哪个冷却时间长哪个好。具体操作看的这里,其实很多地方没有必要这么麻烦,但是自己确实是太菜了,没有自己独立做出来。
1 |
|
F. Lunar New Year and a Recursive Sequence
$\ \ \ \ \ \ \,$感觉这道题操作比E题麻烦一点,但是确实比E题好想呢。
$\ \ \ \ \ \ \,$看到是一个有 $k$ 项的递推式,马上就可以想到矩乘,而前 $k-1$ 项已经确定了是 $1$,我们不妨设要求的 $f_k$ 为 $a$ 。根据他给的式子啊,我们就容易发现,这个递推式的每一项都应该是 $a^x$ 的形式,知道第 $n$ 项是 $a$ 的多少次方就要好处理一些了。
$\ \ \ \ \ \ \,$这样子稍微观察一下矩阵乘法就定义好了:
$\ \ \ \ \ \ \,$转移矩阵:$A=$
$
\begin{bmatrix}0&0&\cdots&0&b_k\\ 1&0&\cdots&0&b_{k-1}\\0&1&\cdots&0&b_{k-2}\\\vdots&\vdots&\ddots&\vdots&\vdots\\0&0&\cdots&1&b_1\end{bmatrix}
$
$\ \ \ \ \ \ \,$初始矩阵:$S=$
$
\begin{bmatrix}0,0,\cdots,0,1\end{bmatrix}
$
$\ \ \ \ \ \ \,$那么第 $n$ 项的指数,就是 $S\cdot A^{n-k}$ 的第 $k$ 项,矩阵乘法取模的时候,根据欧拉定理,因为模数是素数,直接每次模 $mod-1$ 就好了。
$\ \ \ \ \ \ \,$现在问题是,我们知道 $x$,$m$,$mod$,$a^x\%mod=m$,如何求 $a$ 呢?
$\ \ \ \ \ \ \,$好在他给我们的模数很特殊,我们很清楚他的原根为 $3$ ,那么我们可以重新把 $a$ 定义为 $3^s\%mod$,所以原式化为:
$3^{sx}\%mod=m$
$\ \ \ \ \ \ \,$我们可以很轻松用 BSGS 算法知道 $sx\%(mod-1)$的取值,而我们又知道 $x\%(mod-1)$ 的取值,扩展GCD处理一下就好咯~
$\ \ \ \ \ \ \,$然后我们就知道 $s$ 的取值了(也有可能无解),那么答案也就出来了:$f_k=3^s$。
1 |
|