牛客OI测试赛1

题目链接: https://www.nowcoder.com/acm/contest/181#question

A.斐波拉契

求$f[n-1]*f[n+1]-f[n]^2$,$f[n]$为斐波拉契数列第$n$项

算一下前几项不难发现答案为$(-1)^n$,下面用数学归纳法证明一下:

$n=2$时,猜想成立

假设$n=k$时猜想成立,即$f[k-1]*f[k+1]-f[k]^2=(-1)^k$

当$n=k$时,$f[k]f[k+2]-f[k+1]^2=f[k](f[k+1]+f[k])-f[k+1]*(f[k]+f[k-1])=f[k]^2-f[k-1]f[k+1]=(-1)^{k+1}$

得证

#include <cstdio>
#include <algorithm>
#include<vector>
#include<iostream>
#include<cstring>
char s[1000005];
using namespace std;
int main(){
    scanf("%s",s);
    int l=strlen(s);
    int z=s[l-1]-'0';
    if(z%2==0)
        cout<<1<<endl;
    else cout<<-1<<endl;
}

B.送分题

#include <cstdio>
#include <algorithm>
#include<vector>
#include<iostream>
using namespace std;
bool vis[10005];
int a[10005];
vector<int> ans;
int main(){
    long long  a,b;
    cin>>a>>b;
    cout<<a+b<<endl;
}

C.序列

暴力就好,先求出该序列每处的前缀和,用map表示该前缀和存在,对于每次查询,先判断k之前是否查询过,查询过则不用判断,再判断序列和是否是k的倍数,否则,对于$1(sum/z)~k(sum/z)$的前缀和是否都存在

#include <cstdio>
#include <algorithm>
#include<vector>
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=100005;
int ans[maxn];

ll a[maxn];
map<ll,int> mp;

int main(){
    int n,q;
    scanf("%d%d",&n,&q);
    ll sum=0;
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        sum+=a[i];
        mp[sum]=1;
    }
    for(int i=1;i<=q;i++){
        int z;
        scanf("%d",&z);
        if(z>n||sum%z!=0||ans[z]==2){
            printf("No\n");
            continue;
        }

        if(ans[z]==1){
            printf("Yes\n");
            continue;
        }
        for(int i=1;i*(sum/z)<sum;i++){
            if(mp[i*(sum/z)]!=1){
                printf("No\n");
                ans[z]=2;
                break;
            }
        }
        if(ans[z]!=2){
            printf("Yes\n");
            ans[z]=1;
        }
    }
}

D.小叶的巡查

求下直径就好了

#include <cstdio>
#include <algorithm>
#include<vector>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=100005;
vector< pair<int,int> > g[maxn];
int d[maxn];
bool vis[maxn];
void dfs(int u){
    vis[u]=1;
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i].first;
        if(!vis[v]){
            d[v]=d[u]+g[u][i].second;
            dfs(v);
        }
    }
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        g[x].push_back(make_pair(y,z));
        g[y].push_back(make_pair(x,z));
    }
   // cout<<-1<<endl;
    dfs(1);
    int cnt;
    long long dmax=0;
    for(int i=1;i<=n;i++){
        if(d[i]>dmax){
            dmax=d[i];
            cnt=i;
        }
        vis[i]=0;
        d[i]=0;
    }
    dmax=0;
    dfs(cnt);
    for(int i=1;i<=n;i++){
        if(d[i]>dmax){
            dmax=d[i];
        }
    }
    cout<<dmax*10+(1+dmax)*dmax/2<<endl;
}

E.旅行青蛙

最长上升子序列,但是感觉题意有问题,题目的描述应该是最长不上升子序列233,n比较大,用$O(n*log n)$的写法

#include <cstdio>
#include <algorithm>
#include<vector>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=100005;
int dp[maxn];
int a[maxn];
int n;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int cnt=0;
    dp[0]=-1e9;
    for(int i=1;i<=n;i++){
        if(a[i]>=dp[cnt]){
            dp[++cnt]=a[i];
        }
        else {
            int z=upper_bound(dp+1,dp+1+cnt,a[i])-dp;
            dp[z]=a[i];
        }
    }
    cout<<cnt<<endl;
}

F.子序列

由题意知,答案与序列的顺序无关,故先将序列排个序,对于序列中的第i个数,需要相乘的次数为$C{n-1}^{k-1}-C{i-1}^{k-1}-C_{n-i}^{k-1}$。又1e9+7为素数,根据欧拉公式$a^{p-1}\equiv1mod p$

即可得出答案

#include <cstdio>
#include <algorithm>
#include<vector>
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1005;

ll pmod(ll a,ll b){
    if(a==0) return 0;
    if(b==0) return 1;
    if(b==1) return a%mod;
    ll ans=pmod(a,b/2);
    ans=ans*ans%mod;
    if(b&1)
        return ans*a%mod;
    return ans;
}
ll a[maxn];
ll c[maxn][maxn];
int main(){
    for(int i=0;i<=1000;i++)
        c[i][0]=1;
    c[1][1]=1;
    for(int i=1;i<=1000;i++)
        c[i][i]=1;
    for(int i=1;i<=1000;i++)
        for(int j=1;j<i;j++)
        c[i][j]=(c[i-1][j]+c[i-1][j-1])%(mod-1);
    int t;
    scanf("%d",&t);
    while(t--){
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        sort(a+1,a+1+n);
        ll ans=1;
        for(int i=2;i<n;i++){
            ll z=c[n-1][k-1];
            if(n-i>=k-1)
                z-=c[n-i][k-1];
            if(i-1>=k-1)
                z-=c[i-1][k-1];
            z=((z)%(mod-1)+mod-1)%(mod-1);
            z=pmod(a[i],z);
            ans=ans*z%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/dlutjwh/p/10976341.html