Codeforces Round_489 & EduRound_47

EduRound_47_C Annoying Present

1009C

每次添加的时候,必然会加上n个x,只有d的数目是不确定的。这里采用贪心的方法,如果d>0,就让d尽可能多,把位置定在两端的某处。如果d<0就让它尽可能少,位置定在中间。中间的这些过程还是用long long比较精确。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#define maxn 115
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;

int m,n,x,d;
long long sum;

int main()
{
    scanf("%d%d",&n,&m);
    sum=0;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&x,&d);
        sum+=1LL*x*n;
        if(d>0)sum+=1LL*d*(1LL*(n-1)*n)/2;
        else
        {
            sum+=1LL*d*(n/2+1)*(n/2);
            if(n%2==0)sum-=1LL*d*(n/2);
        }
    }
    printf("%.15lf\n",1.0*sum/n);
    return 0;
}

EduRound_47_E Intercity Travelling

1009E

答案的p*2^(n-1)实际上就是所有方案的总花费之和。

推了个式子,n个位置时总的结果是a[n]+\sum_{i=1}^{n-1}a[i]*[(n-i+1)*2^{n-i}-(n-i)*2^{n-i-1}]

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#define maxn 1000050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
const ll mod = 998244353;

int n;
ll a[maxn];

ll mi(ll a,int x)
{
    if(x==0)return 1;
    ll tmp=mi(a,x/2);
    ll ans=(tmp*tmp)%mod;
    if(x%2==1)ans=(ans*a)%mod;
    return ans;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%I64d",&a[i]);
    ll sum=0;
    for(int i=1;i<n;i++)
    {
        int t=n-i+1;
        sum=(sum+(a[i]*((t*mi(1LL*2,t-1))%mod-((t-1)*mi(1LL*2,t-2))%mod))%mod)%mod;
    }
    printf("%I64d\n",(sum+a[n])%mod);
    return 0;
}

Round_498_D Two Strings Swaps

1006D

对于位置i对应的一组4个字符a[i],b[i],a[n-i-1],b[n-i-1],如果有两对一样的就不用更改。但是最后的时候只能改a不能改b,因此如果a的两个位置相同,b的两个位置不同且都与a不同,这种情况下最后要改两次。

对于奇数长度的串,单独判断一下中间的位置。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
const ll mod = 998244353;

int n;
char a[maxn],b[maxn];

int main()
{
    scanf("%d",&n);
    scanf("%s%s",a,b);
    int ans=0;
    for(int i=0;i<n/2;i++)
    {
        int tmp=(a[i]==a[n-i-1])+(b[i]==b[n-i-1]);
        if(a[i]==a[n-i-1]&&b[i]!=b[n-i-1])tmp=0;
        tmp=max(tmp,(a[i]==b[i])+(a[n-i-1]==b[n-i-1]));
        tmp=max(tmp,(a[i]==b[n-i-1])+(a[n-i-1]==b[i]));
        ans+=(2-tmp);
    }
    if(n%2==1){if(a[n/2]!=b[n/2])ans++;}
    printf("%d\n",ans);
    return 0;
}

Round_498_E Military Problem

1006E

从根节点1开始进行一遍DFS,保存每个点的时间戳,节点按时间戳的排列,以每个点为根的子树的节点数目。

对于每次询问,如果u的子树没有k个节点即无解,否则就按照时间戳找出子树上的第k个节点。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#define maxn 200050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
const ll mod = 998244353;

int n,m,x,no,k;
int sum[maxn];
int pos[maxn],num[maxn];
bool flag[maxn];
vector<int>maze[maxn];

int dfs(int u)
{
    int res=1;
    int len=maze[u].size();
    flag[u]=1;
    num[u]=no;
    pos[no++]=u;
    for(int i=0;i<len;i++)
    {
        int v=maze[u][i];
        if(!flag[v])
            res+=dfs(v);
    }
    return sum[u]=res;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)maze[i].clear();
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&x);
        maze[x].push_back(i);
    }
    memset(flag,0,sizeof(flag));
    for(int i=1;i<=n;i++)
        sort(maze[i].begin(),maze[i].end());
    no=1;
    int ans=dfs(1);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&x,&k);
        if(sum[x]<k)printf("-1\n");
        else printf("%d\n",pos[num[x]+k-1]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/NPU_SXY/article/details/81146454
今日推荐