牛客寒假算法集训 1

A题

小a的计算器(水题)

链接:https://ac.nowcoder.com/acm/contest/317/A
来源:牛客网

小a的数学基础实在太差了,以至于他只会用计算器算数。他的计算器比较特殊,只有+,,×,/+,−,×,/(即加减乘除)四种运算。
经过一番周折,小a终于算出了他想要的数,但是他却忘记了最初的数是什么。不过幸运的是他记下了整个操作序列,他想请你帮他算出最初的数

思路

就是用个数组,将操作序列记录下来,然后逆序进行求解,这里对乘的运算的逆是除,但是,要排除除以0的情况,进行下特判

代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long n,m;
    cin>>n>>m;
    long long op[105],x[105];
    for(int i=1;i<=n;i++) cin>>op[i]>>x[i];
    for(int i=n;i>=1;i--){
        if(op[i]==1) m-=x[i];
        else if(op[i]==2)m+=x[i];
        else if(op[i]==3) {
            if(x[i]==0) m=0;
            else m=m/x[i];
        }
        else m=m*x[i];
    }
    cout<<m<<endl;
    return 0;
}

 

B题

小a与204

链接:https://ac.nowcoder.com/acm/contest/317/B
来源:牛客网

小a非常喜欢204204这个数字,因为a+k=204′a′+′k′=204。
现在他有一个长度为nn的序列,其中只含有2,0,42,0,4这三种数字
aiai为序列中第ii个数,你需要重新排列这个数列,使得ni=1(aiai1)2∑i=1n(ai−ai−1)2最大(公式的含义是:每个数与前一个数差的平方的和)
注意:我们默认a0=0a0=0

思路

贪心,我们需要对一个序列进行排序,是的两两之差的平方,要尽可能的大。

这里我们只需要先将2 0 4这三个数的次数统计一下,然后从1开始,对于前一个数进行判断然后放值进行就行了

如果前一个数是0,那优先放4,如果4没了,就放2,如果2也没了,就放0,其他数也同理。

代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;
    long long ans=0;
    int a=0,b=0,c=0;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>m;
        if(m==0) a++;
        if(m==2) b++;
        if(m==4) c++;
    }
    int t=0;
    for(int i=0;i<n;i++){
        if(t==0){
            if(c>0) c--,ans+=16,t=4;
            else if(b>0) b--,ans+=4,t=2;
            else a--;
        }
        else if(t==2){
            if(c>0) c--,ans+=4,t=4;
            else if(a>0) a--,ans+=4,t=0;
            else b--;
        }
        else if(t==4){
            if(a>0) a--,ans+=16,t=0;
            else if(b>0) b--,ans+=4,t=2;
            else c--;
        }
    }
    cout<<ans<<endl;
    return 0;
}

C题

小a与星际探索

链接:https://ac.nowcoder.com/acm/contest/317/C
来源:牛客网

小a正在玩一款星际探索游戏,小a需要驾驶着飞船从11号星球出发前往nn号星球。其中每个星球有一个能量指数pp。星球ii能到达星球jj当且仅当pi>pjpi>pj。
同时小a的飞船还有一个耐久度tt,初始时为11号点的能量指数,若小a前往星球jj,那么飞船的耐久度会变为tpjt⊕pj(即tt异或pjpj,关于其定义请自行百度)
小a想知道到达nn号星球时耐久度最大为多少

注意:对于每个位置来说,从它出发可以到达的位置仅与两者的pp有关,与下标无关

思路

背包问题的dp

首先我们队这个能量指数进行排序,使得对于每个星球,在他之后的所有星球都可以从这个星球到达。

然后就开始dp呗,我自己的代码好像不是正确的。所以再贴一份官方的代码

代码

#include <bits/stdc++.h>
using namespace std;
int n;
struct node{
    int a,b;
}num[3005];
 int cmp(node x,node y){
    if(x.b==y.b) return x.a<y.b;
    return x.b>y.b;
 }
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>num[i].b;
        num[i].a=i;
    }
    sort(num,num+n,cmp);
    int s,t;
    //for(int i=0;i<n;i++) cout<<num[i].a<<' '<<num[i].b<<endl;
    for(int i=0;i<n;i++){
        if(num[i].a==0) s=i;
        if(num[i].a==n-1) t=i;
    }
    //cout<<s<<' '<<t<<endl;
    if(s>t) cout<<-1<<endl;
    else{
        int dp[3005];
        memset(dp,0,sizeof(dp));
        dp[s]=num[s].b;
        for(int i=s+1;i<=t;i++){
            for(int j=s;j<i;j++){
                dp[i]=max(dp[i],dp[j]^num[i].b);
            }
        }
        if(!dp[t]) cout<<-1<<endl;
        else cout<<dp[t]<<endl;
    }
    return 0;
}
#include<bits/stdc++.h>
#define LL long long 
using namespace std;
const int MAXN = 10003, INF = 1e9 + 10;
void chmin(int &a, int b) {a = (a < b ? a : b);}
void chmax(int &a, int b) {a = (a > b ? a : b);}
int sqr(int x) {return x * x;}
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, mx;
bool f[MAXN][MAXN];
struct Node {
    int id, val;
    bool operator < (const Node &rhs) const {
        return val > rhs.val;
    }
}a[MAXN];
signed main() {
    //freopen("a2.in", "r", stdin);
    //cout << (457 ^ 23);
    N = read();
    for(int i = 1; i <= N; i++) a[i].id = i, a[i].val = read(); mx = 6001;
    sort(a + 1, a + N + 1);
    for(int i = 1, flag = 1; i <= N; i++) {
        if(a[i].id == 1) {flag = 0, f[i][a[i].val] = 1; continue;}
        if(flag) continue;
        if(a[i].id == N) {
            int k = i - 1;
            while(k && a[i].val == a[k].val) k--;
            if(!k) break;
            for(int j = mx; j >= 0; j--) {
                f[i][j] |= f[k][j ^ a[i].val];
                if(f[i][j]) {printf("%d", j); return 0;}
            } 
            break;
        }
        else if(a[i].val == a[i - 1].val) {
            memcpy(f[i], f[i - 1], sizeof(f[i]));
        }
        else {
            for(int j = 0; j <= mx; j++) 
                f[i][j] |= (f[i - 1][j ^ a[i].val] | f[i - 1][j]);     
        }
    }
    puts("-1");
    return 0;
}

D题

小a与黄金街道

链接:https://ac.nowcoder.com/acm/contest/317/D
来源:牛客网

小a和小b来到了一条布满了黄金的街道上。它们想要带几块黄金回去,然而这里的城管担心他们拿走的太多,于是要求小a和小b通过做一个游戏来决定最后得到的黄金的数量。
游戏规则是这样的:
假设道路长度为nn米(左端点为00,右端点为nn),同时给出一个数kk(下面会提到kk的用法)
设小a初始时的黄金数量为AA,小b初始时的黄金数量为BB
小a从11出发走向n1n−1,小b从n1n−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会变为Akx(kg)A∗kx(kg),小b的黄金数量BB会变为Bky(kg)B∗ky(kg)
当小a到达n1n−1时游戏结束
小a想知道在游戏结束时A+BA+B的值
答案对109+7109+7取模

思路

首先我们需要理解一个知识点,对于gcd(n,x)=1 时,x<n,gcd(n,n-x)=1,这个是满足的

那这个问题就转换成我们要求在n以内有多少个与n互质的个数,也就是欧拉函数。

当然只求个数是不行的,我们需要知道这些数的和,就为ϕ(n)*n/2,这个可以推一下

代码

#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int phi(int n)
{
    int ans = n;
    for(int i = 2;i*i <= n;i++)if(n % i == 0)
    {
        ans -= ans/i;
        while(n % i == 0)
            n /= i;
    }
    if(n != 1)
        ans -= ans/n;
    return ans;
}
long long power_mod(long long a,long long b){
    long long ans=1;
    a=a%mod;
    while(b){
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
int main()
{
    int n;
    long long k,a,b;
    ios::sync_with_stdio(false);
    cin>>n>>k>>a>>b;
    long long x=(long long)phi(n)*n/2;
    a=a%mod;
    b=b%mod;
    long long ans=(a+b)*power_mod(k,x)%mod;
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2019-02-25 15:40  maybe96  阅读(127)  评论(0编辑  收藏  举报