EduRound_47_C Annoying Present
每次添加的时候,必然会加上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
答案的p*2^(n-1)实际上就是所有方案的总花费之和。
推了个式子,n个位置时总的结果是
#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
对于位置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
从根节点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;
}