Educational Codeforces Round 7

来源:互联网 发布:什么听歌识曲软件好 编辑:程序博客网 时间:2024/06/16 06:30

C. Not Equal on a Segment

预处理找到每个位置开始的最先出现的不同的数。

#include <bits/stdc++.h>using namespace std;#define ll long longint a[200010];int diff[200010];int main(){    int n,m;    cin>>n>>m;    for(int i=1;i<=n;i++){        scanf("%d",&a[i]);    }    diff[n]=n+1;    for(int i=n-1;i>=1;i--){        if(a[i]==a[i+1]){            diff[i]=diff[i+1];        }else{            diff[i]=i+1;        }    }    while(m--){        int l,r,x;        scanf("%d%d%d",&l,&r,&x);        if(a[l]!=x){            printf("%d\n",l);        }else{            if(diff[l]<=r){                printf("%d\n",diff[l]);            }else{                printf("-1\n");            }        }       }    return 0;}

D. Optimal Number Permutation

构造,只要相同的数距离恰当,总可以使得s=0

#include <bits/stdc++.h>using namespace std;#define ll long longint ans[1000010];int main(){    int n;    cin>>n;    if(n==1){        cout<<"1 1"<<endl;        return 0;    }    if(n==2){        cout<<"1 1 2 2"<<endl;        return 0;    }    int l=1;    int r=n;    int num=1;    while(l<r){        ans[l]=ans[r]=num;        num+=2;        l++;    r--;    }    l=n+1;    r=2*n-1;    num=2;    while(l<r){        ans[l]=ans[r]=num;        num+=2;        l++;    r--;    }    for(int i=1;i<=n*2;i++){        if(ans[i]){            printf("%d ",ans[i]);        }else{            printf("%d ",n);        }    }    return 0;}

E. Ants in Leaves

通过分析可以发现,不妨让深度小的叶子比深度大的先回到根,这样不会影响答案。我们依次处理根的所有子树,把该子树下的所有叶子高度找出来,排序,按高度从小到大处理。假设排序后leaves(i)是第i个叶子的高度,ans(i)是考察到此叶子时的答案,ans(i)=max(ans(i1)+1,leaves(i))总是成立的。从另一个角度,ans表明了路径会“阻塞”到什么时候。

#include <bits/stdc++.h>using namespace std;const int maxn = 500010;vector<int> adj[maxn];bool vis[maxn];int depth = 0;int ans=0;vector<int> leaves;void dfs(int u){    depth++;    vis[u]=1;    int sz = adj[u].size();    bool flag=1;    for(int i=0;i<sz;i++){        int v=adj[u][i];        if(vis[v])continue;        dfs(v);        flag=0;    }    if(flag){        leaves.push_back(depth);    }    depth--;}int main(){    int n;    cin>>n;    for(int i=1;i<n;i++){        int u,v;        scanf("%d%d",&u,&v);        adj[u].push_back(v);        adj[v].push_back(u);    }    int sz = adj[1].size();    vis[1]=1;    for(int i=0;i<sz;i++){        int u = adj[1][i];        leaves.clear();        dfs(u);        sort(leaves.begin(),leaves.end());        int leanum = leaves.size();        int tmp=0;        for(int j=0;j<leanum;j++){            tmp=max(tmp+1,leaves[j]);        }        ans=max(ans,tmp);    }    cout<<ans<<endl;    return 0;}

F. The Sum of the k-th Powers

看了官方题解,不得不说这题有点神。首先要知道一点,不管k是多少,肯定有一个最高次为k+1的公式(题目已经提示了)。然后i=k+2的部分,是很容易用快速幂计算出来的,这个时候,我们可以用拉格朗日多项式得到一个通项公式(唯一的),然后计算第n项即可。

#include <bits/stdc++.h>using namespace std;#define ll long longconst ll mod = 1e9+7;ll mod_pow(ll a,ll n){    ll re=1;    while(n){        if(n&1){            re*=a;            re%=mod;        }        a*=a;        a%=mod;        n>>=1;    }    return re;}ll y[1000010];void ExEuclid(ll a,ll b,ll &x,ll &y,ll &q){      if(b==0){          x=1;y=0;q=a;          return;      }      ExEuclid(b,a%b,y,x,q);      y-=x*(a/b);  }ll inv(ll num){      ll x,y,q;      ExEuclid(num,mod,x,y,q);      if(q==1)return (x+mod)%mod;  }int main(){    ll n,k;    cin>>n>>k;    for(int i=1;i<=k+2;i++){        y[i]=y[i-1]+mod_pow(i,k);        y[i]%=mod;    }    if(n<=k+2){        cout<<y[n]<<endl;        return 0;    }    ll dividend=1;    ll divisor=1;    for(int i = 1;i<=k+2;i++){        dividend *= (n-i);        dividend %= mod;    }    for(int i=1;i<=k+1;i++){        divisor *= i;        divisor %= mod;    }    bool minus = !(k&1);    ll ans = 0;    for(int i=1;i<=k+2;i++){        ll tmp = (dividend*inv(n-i))%mod * inv(divisor);        tmp %= mod;        tmp *= y[i];        tmp %= mod;        if(minus)tmp=-tmp;        minus = !minus;        ans += tmp;        ans += mod;        ans %= mod;        divisor*=inv(k+2-i);        divisor%=mod;        divisor*=i;        divisor%=mod;    }    cout<<ans<<endl;    return 0;}
0 0
原创粉丝点击