1.小a的计算器
题意:给你运算的过程和结果,让你逆推最开始的数
算法:简单模拟
思想:根据加减乘除四则运算反着算,如果是加变减,减变加,乘变除,除变乘。从后往前算。
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
long long b[105];
int a[105];
int main(){
int n;
long long x;
cin>>n>>x;
for(int i = 0; i < n; i++){
cin>>a[i]>>b[i];
}
for(int i = n-1; i >= 0; i--){
if(a[i] == 4)x *= b[i];
else if(a[i] == 3)x /= b[i];
else if(a[i] == 2) x += b[i];
else x -= b[i];
}
cout<<x<<endl;
return 0;
}
2.小a与"204"
链接:https://ac.nowcoder.com/acm/contest/317/B
算法:简单模拟
题意:给你一个数组,数组里只包含2,4,0这三个数,问你怎么排列数组,使前一项减后一项的平方和最大。
思想:先统计2,4, 0的个数,当尽可能的4和0搭配时,前一项减后一项的平方和最大。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define maxn 1e5+5;
vector<int>v;
int main(){
int n, a = 0, b = 0, c = 0, t;
cin>>n;
for(int i = 0; i < n;i++ ){//统计2,0,4的个数
cin>>t;
if(t == 0)a++;
else if(t == 4)b++;
else c++;
}
while(a && b){//尽可能的2和4进行搭配
v.push_back(4);
v.push_back(0);
a--;
b--;
}
if(a > 0){//当0有剩余的时候
while(a && c){//0和2进行搭配
v.push_back(2);
v.push_back(0);
a--;
c--;
}
while(a > 0){//0有剩余
v.push_back(0);
a--;
}
while(c > 0){//2有剩余
v.push_back(2);
c--;
}
}
if(b > 0){//4有剩余
while(b && c){//4和2进行匹配
v.push_back(4);
v.push_back(2);
b--;
c--;
}
while(b ){//4有剩余
v.push_back(4);
b--;
}
while(c ){//2有剩余
v.push_back(2);
c--;
}
}
if(!a && !b ){//0和4都没有剩余,只剩下2
while(c){
v.push_back(2);
c--;
}
}
// for(int i = 0; i < v.size(); i++){输出看看逻辑有没有问题
// cout<<v[i]<<" ";
// }
long long ans = v[0]*v[0];
int pre = v[0];
for(int i = 1; i < v.size(); i++){//进行运算
ans += (v[i] - pre)*(v[i]-pre);
pre = v[i];
// cout<<ans<<endl;
}
cout<<ans<<endl;
}
3.小a与星际探索
链接:https://ac.nowcoder.com/acm/contest/317/C
算法:动态规划
题意:如果前面的数比后面的数大(不一定是连续的),那么此时的耐力值就跟候面的数异或一下,求最大的耐力值
思想:采用动态规划更新某点的最大耐力值
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 3005//本题采用动态规划,寻找到当前位置的最大值。
int a[maxn], vis[maxn], dp[maxn];
int main()
{
int n;
cin>>n;
for(int i = 1; i <= n; i++)cin>>a[i];
memset(vis, 0, sizeof(vis));
dp[1] = a[1];
vis[1] = 1;
for(int i = 2; i <= n; i++){
for(int j = 1; j < i; j++){
if(vis[j] == 0)continue;//后面没有更新到的数
if(a[j] <= a[i])continue;//前面的不比后面的大
dp[i] = max(dp[i], dp[j]^a[i]);//更新值
vis[i] = 1;
}
}
if(vis[n]){
cout<<dp[n]<<endl;
}
else cout<<-1<<endl;//无法更新到n
return 0;
}
4.小a与黄金街道
链接:https://ac.nowcoder.com/acm/contest/317/D
算法:快速幂,同余模定理,欧拉函数
题意:
小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的黄金数量A会变为A∗k^x(kg),小b的黄金数量B会变为B∗k^y(kg)
当小a到达n−1n−1时游戏结束
小a想知道在游戏结束时A+BA+B的值
答案对109+7109+7取模
思想:通过题意gcd(n,x)=1可以看出来,需要欧拉函数,而且A*k^x*k^z = A * k^(x+z),所以只需要根据欧拉函数求出互质的数之和
根据Euler(x)∗x/2,就能求出互质的数之和,然后根据快速幂求出最后的结果。
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const long long mod = 1e9+7;
#define LL long long
LL quick_pow(LL a, LL b){//快速幂 同余模定理
LL base = a;
LL ans = 1;
while(b){
if(b & 1)ans = (ans * base) % mod;
b >>= 1;
base = (base * base) % mod;
}
return ans;
}
LL Euler(int n){//欧拉函数
LL ans = n;
for(int i = 2; i <= sqrt(n); i++){
if(n % i == 0){
ans = ans / i * (i - 1);
while(n % i == 0)
n /= i;
}
}
if(n > 1){
ans = ans / n *(n-1);
}
return ans;
return 0;
}
int main(){
int n, k, a, b;
cin>>n>>k>>a>>b;
LL ans = Euler(n)* n / 2;
LL key = quick_pow(k, ans);
cout<<(key*(a+b)%mod)%mod<<endl;
return 0;}
5.小a的子序列
链接:https://ac.nowcoder.com/acm/contest/317/F
算法:动态规划
题意:小a有一个长度为nn的序列,但是他忘了这个序列的样子,他只记得序列中的数大小在[1,V]内
你可以任意选择一些位置,并给它们赋值来组成一段子序列,需要满足序列中的数严格递增
一段子序列的“萌值”定义为序列中除最大数外所有数的乘积,若只有1个数则为1
他想请你求出所有合法子序列的“萌值”的和
不同子序列的定义为:存在某个值不同 或 在原序列中的位置不同
输出答案对1e9+7取模
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll dp[5005][5005];
const ll mod=1e9+7;
int n,v;
int main()
{
scanf("%d%d",&n,&v);
for(int i=1;i<=v;i++) dp[i][1]=1;
for(int i=2;i<=n;i++)
{
ll sum=1;
for(int j=1;j<=v;j++)
{
dp[j][i]=(dp[j][i-1]+sum)%mod;
sum=(sum+dp[j][i-1]*(ll)j)%mod;
}
}
ll ans=0;
for(int i=1;i<=v;i++) ans+=dp[i][n];
cout<<ans%mod<<endl;
}