集训营涵盖知识点:
第一场:模拟、贪心、动态规划、数学、数据结构
A | 小a的计算器 |
链接:https://ac.nowcoder.com/acm/contest/317/A
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
小a的数学基础实在太差了,以至于他只会用计算器算数。他的计算器比较特殊,只有+,−,×,/+,−,×,/(即加减乘除)四种运算。
经过一番周折,小a终于算出了他想要的数,但是他却忘记了最初的数是什么。不过幸运的是他记下了整个操作序列,他想请你帮他算出最初的数
第一行两个整数n,Xn,X,分别表示操作次数和最终的数
接下来nn行表示操作序列,每行两个数opt,xopt,x
若opt=1opt=1,则表示将当前数加xx
若opt=2opt=2,则表示将当前数减xx
若opt=3opt=3,则表示将当前数乘xx
若opt=4opt=4,则表示将当前数除以xx
一个整数表示最初的数
示例1
复制
4 6
1 3
2 1
3 3
4 2
复制
2
样例1解释
2+3=55−1=44∗3=1212/2=62+3=55−1=44∗3=1212/2=6
示例2
复制
3 292
3 2
4 3
4 3
复制
1314
n⩽100,0
用结构体存储运算标识,将运算反着进行
#include
using namespace std;
struct node
{
int a;
int b;
};
node num[1005];
int main()
{
int n;
long long x;
cin>>n>>x;
for(int i=1;i<=n;i++)
{
cin>>num[i].a>>num[i].b;
}
for(int i=n;i>=1;i--)
{
if(num[i].a==1)
{
x-=num[i].b;
}
else if(num[i].a==2)
{
x+=num[i].b;
}
else if(num[i].a==3)
{
x=x/num[i].b;
}
else
{
x=x*num[i].b;
}
}
cout<
B | 小a与"204" |
链接:https://ac.nowcoder.com/acm/contest/317/B
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
小a非常喜欢204204这个数字,因为′a′+′k′=204′a′+′k′=204。
现在他有一个长度为nn的序列,其中只含有2,0,42,0,4这三种数字
设aiai为序列中第ii个数,你需要重新排列这个数列,使得∑ni=1(ai−ai−1)2∑i=1n(ai−ai−1)2最大(公式的含义是:每个数与前一个数差的平方的和)
注意:我们默认a0=0a0=0
第一行一个整数nn
接下来一行nn个整数,第ii个数表示aiai
输出一个整数,表示∑ni=1(ai−ai−1)2∑i=1n(ai−ai−1)2的最大值
示例1
复制
2
2 4
复制
20
样例1解释:按(4,2)(4,2)排列是最优的,此时sum=(4−0)2+(2−4)2=20sum=(4−0)2+(2−4)2=20
示例2
复制
3
2 0 4
复制
36
样例2解释:按(4,0,2)(4,0,2)排列是最优的,此时sum=(4−0)2+(0−4)2+(2−0)2=36sum=(4−0)2+(0−4)2+(2−0)2=36
示例3
复制
5
2 4 0 2 4
复制
52
1⩽n⩽1051⩽n⩽105,保证aiai为2/0/42/0/4中的数
由于默认a0=0,那么第一个数应该是最大的。
接下来要想得到最大值,第二个应为最小数,第三个为次最大,第四个为次最小以此类推。
则奇数位的数字从大到小,偶数位的数字从小到大,可以求得最大值
#include
#include
using namespace std;
int a[100005];
int b[100005];
int main()
{
int n;
cin>>n;
for(int i=1; i<=n; i++)
cin>>a[i];
sort(a+1,a+1+n);
int l=1,r=n;
for(int i=1; i<=n; i++)
{
if(i&1)
b[i]=a[r--];
else
{
b[i]=a[l++];
}
}
long long num=0;
for(int i=1;i<=n;i++)
{
num+=(b[i]-b[i-1])*(b[i]-b[i-1]);
}
cout<
C | 小a与星际探索 |
链接:https://ac.nowcoder.com/acm/contest/317/C
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
小a正在玩一款星际探索游戏,小a需要驾驶着飞船从11号星球出发前往nn号星球。其中每个星球有一个能量指数pp。星球ii能到达星球jj当且仅当pi>pjpi>pj。
同时小a的飞船还有一个耐久度tt,初始时为11号点的能量指数,若小a前往星球jj,那么飞船的耐久度会变为t⊕pjt⊕pj(即tt异或pjpj,关于其定义请自行百度)
小a想知道到达nn号星球时耐久度最大为多少
注意:对于每个位置来说,从它出发可以到达的位置仅与两者的pp有关,与下标无关
第一行一个整数nn,表示星球数
接下来一行有nn个整数,第ii个整数表示pipi
一个整数表示到达nn号星球时最大的耐久度
若不能到达nn号星球或到达时的最大耐久度为00则输出−1−1
示例1
复制
3
457 456 23
复制
478
小a有两种方法到达33号星球
第一种:1→2→31→2→3,最终耐久度为457⊕456⊕23=22457⊕456⊕23=22
第二种:1→31→3,最终耐久度为457⊕23=478457⊕23=478
示例2
复制
4
2 4 4 2
复制
-1
示例3
复制
5
234 233 123 2333 23
复制
253
1⩽n,∀pi⩽3000
用线性基求最大异或和
#include
#include
#include
#define ll long long
using namespace std;
const int maxn = 1e5*5;
int a[maxn], p[maxn];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> p[i];
for (int i = 1; i = 0; j--)
if (p[i]>>j&1&&p[0]>p[i]&&p[i]>p[n])
if (!a[j]) {
a[j] = p[i];
break;
}
else
p[i] ^= a[j];
int ans = p[0] ^ p[n - 1];
for (int i = 14; i >= 0; i--)
ans = max(ans, ans^a[i]);
cout << (p[0]>p[n-1]?ans:-1) << endl;
return 0;
}
D | 小a与黄金街道 |
链接:https://ac.nowcoder.com/acm/contest/317/D
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
小a和小b来到了一条布满了黄金的街道上。它们想要带几块黄金回去,然而这里的城管担心他们拿走的太多,于是要求小a和小b通过做一个游戏来决定最后得到的黄金的数量。
游戏规则是这样的:
假设道路长度为nn米(左端点为00,右端点为nn),同时给出一个数kk(下面会提到kk的用法)
设小a初始时的黄金数量为AA,小b初始时的黄金数量为BB
小a从11出发走向n−1n−1,小b从n−1n−1出发走向11,两人的速度均为1m/s1m/s
假设某一时刻(必须为整数)小a的位置为xx,小b的位置为yy,若gcd(n,x)=1gcd(n,x)=1且gcd(n,y)=1gcd(n,y)=1,那么小a的黄金数量AA会变为A∗kx(kg)A∗kx(kg),小b的黄金数量BB会变为B∗ky(kg)B∗ky(kg)
当小a到达n−1n−1时游戏结束
小a想知道在游戏结束时A+BA+B的值
答案对109+7109+7取模
一行四个整数n,k,A,Bn,k,A,B
输出一个整数表示答案
示例1
复制
4 2 1 1
复制
32
初始时A=1,B=1A=1,B=1
第一个时刻如图所示,小a在11,小b在33,满足条件,此时A=1∗21=2,B=1∗23=8A=1∗21=2,B=1∗23=8
第二个时刻小a在22,小b在22,不满足条件
第三个时刻小a在33,小b在11,满足条件,此时A=2∗23=16,B=8∗21=16A=2∗23=16,B=8∗21=16
此时游戏结束A=2∗23=16,B=8∗21=16A=2∗23=16,B=8∗21=16
A+B=32A+B=32
示例2
复制
5 1 1 1
复制
2
保证3⩽n⩽108,A,B,k⩽10133⩽n⩽108,1⩽A,B,k⩽1013
欧拉函数+快速幂
若gcd(n,x)=1,则gcd(n,n-x)=gcd(n,y)=1。
因为x,y∈(1<-->n-1),则(X1+X2+...+Xi)=(Y1+Y2+...+Yi )。
所以A*k^(X1+X2+...+Xi) + B*k^(Y1+Y2+...+Yi ) = (A+B)*k^(M1+M2+Mi)
(M1+M2+....+Mi)=euler*n/2;
#include
#define ll long long
using namespace std;
const int mod= 1e9+7;
ll quick(ll m,ll k)//快速幂
{
ll res=1;
while(k)
{
if(k&1) res=res*m%mod;
m=m*m%mod;
k>>=1;
}
return res;
}
int main()
{
ll n,k,a,b;
cin>>n>>k>>a>>b;
ll euler=n,t=n;
for(ll p=2;p*p<=n;p++)
{
if(n%p==0)//若等于0,则表明p为n的质因子
{
euler=euler/p*(p-1);//euler=n*(1-1/Pi)
while(n%p==0)//将Pi这个因子全部除净
n/=p;
}
}
if(n>1)//若n还没有被除完
euler=euler/n*(n-1);
ll sum=euler/2*t;
cout<<(a+b)*quick(k,sum)%mod<