感想

我好菜啊,只能做出前三题……

以后再也不会打yutaka1999的比赛了……人神题目也神……

这一场……打得我……如果以我实力的话只能作出AC两题,B还是wzy教我的(%%%)

A - Digits Sum

题目大意

给定一个数K,求正整数A,B使得A+B=KA,B 各位数字之和最小,输出最小的各位数字之和。

思路

显然不进位的加是最优的,尽量减少进位的次数,如果K=10x则答案为10(必须进一次位),否则答案就为K的各位数字相加。

代码

#include <cstdio>

int n;

int main()
{
  scanf("%d",&n);
  int sum=0;
  while(n)
    {
      sum+=n%10;
      n/=10;
    }
  if(sum==1)
    {
      sum=10;
    }
  printf("%d\n",sum);
  return 0;
}

B - RGB Coloring

题目大意

给一张n个格子的纸,不允许旋转和轴对称翻转,现在规定,红色的权值为A,蓝色的权值为B,绿色的权值为A+B,不涂色权值为0,要求给纸涂色使得这张纸的权值之和为K,求涂色方案数%998244353。

n,A,B3×105,K18×1010(然而原题为啥是18×1010……)

思路

枚举红色的个数,可以得到蓝色的个数,然后分别乱填红色和蓝色,红色和蓝色都涂过的格子就是绿色。

代码

#include <cstdio>

const int mo=998244353;
const int maxn=300000;

int n,a,b,ans,fac[maxn+10],ifac[maxn+10];
long long k;

int c(int a,int b)
{
  return 1ll*fac[a]*ifac[b]%mo*ifac[a-b]%mo;
}

int main()
{
  scanf("%d%d%d%lld",&n,&a,&b,&k);
  fac[0]=1;
  for(int i=1; i<=n; ++i)
    {
      fac[i]=1ll*fac[i-1]*i%mo;
    }
  ifac[0]=ifac[1]=1;
  for(int i=2; i<=n; ++i)
    {
      ifac[i]=1ll*(mo-mo/i)*ifac[mo%i]%mo;
    }
  for(int i=2; i<=n; ++i)
    {
      ifac[i]=1ll*ifac[i]*ifac[i-1]%mo;
    }
  for(int i=0; i<=n; ++i)
    {
      if((k-1ll*a*i)%b)
        {
          continue;
        }
      long long cntb=(k-1ll*a*i)/b;
      if((cntb>n)||(cntb<0))
        {
          continue;
        }
      ans=ans+1ll*c(n,i)*c(n,cntb)%mo;
      if(ans>=mo)
        {
          ans-=mo;
        }
    }
  printf("%d\n",ans);
  return 0;
}

C - Interval Game

题目大意

Alice和Bob在玩一个游戏,初始时Bob在数轴原点,Alice手上有N条线段,每次进行操作:

  • Alice选择一条之前没有选择过的线段;
  • Bob走到线段上任意一点;

最后Bob回到数轴原点。

令Bob走过的距离为K,Alice想要K尽量大,Bob想要K尽量小,求最终K是多少。

思路

这道题很容易想到一个贪心方案:

按线段右端点从小到大排序,令排序后的线段序列为A

按线段左端点从大到小排序,令排序后的线段序列为B

每次比较 右端点最小的那条线段到当前点的距离 与 左端点最大的那条线段到当前点的距离,并走向更大的那个。

但是如果开始时两边到坐标原点的距离一样,则两边都尝试一遍。

代码

#include <cstdio>
#include <cmath>
#include <algorithm>

const int maxn=100000;

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

struct seg
{
  int l,r,flag;
};

seg s[maxn+10];

bool cmpl(int a,int b)
{
  return s[a].l>s[b].l;
}

bool cmpr(int a,int b)
{
  return s[a].r<s[b].r;
}

int n,a[maxn+10],b[maxn+10];
long long rans;

inline int dist(int now,int to)
{
  if(now<s[to].l)
    {
      return s[to].l-now;
    }
  else if(now>s[to].r)
    {
      return now-s[to].r;
    }
  else
    {
      return 0;
    }
}

inline int getnow(int now,int to)
{
  if(now<s[to].l)
    {
      return s[to].l;
    }
  else if(now>s[to].r)
    {
      return s[to].r;
    }
  else
    {
      return now;
    }
}

int main()
{
  n=read();
  for(int i=1; i<=n; ++i)
    {
      s[i].l=read();
      s[i].r=read();
      a[i]=b[i]=i;
    }
  std::sort(a+1,a+n+1,cmpl);
  std::sort(b+1,b+n+1,cmpr);
  int left=1,right=1,now=0;
  long long ans=0;
  s[a[1]].flag=1;
  ans+=dist(now,a[1]);
  now=getnow(now,a[1]);
  for(int i=1; i<n; ++i)
    {
      while(s[a[left]].flag)
        {
          ++left;
        }
      while(s[b[right]].flag)
        {
          ++right;
        }
      if(dist(now,a[left])>dist(now,b[right]))
        {
          s[a[left]].flag=1;
          ans+=dist(now,a[left]);
          now=getnow(now,a[left]);
        }
      else
        {
          s[b[right]].flag=1;
          ans+=dist(now,b[right]);
          now=getnow(now,b[right]);
        }
    }
  for(int i=1; i<=n; ++i)
    {
      s[i].flag=0;
    }
  rans=ans+abs(now);
  left=right=1;
  now=ans=0;
  s[b[1]].flag=1;
  ans+=dist(now,b[1]);
  now=getnow(now,b[1]);
  for(int i=1; i<n; ++i)
    {
      while(s[a[left]].flag)
        {
          ++left;
        }
      while(s[b[right]].flag)
        {
          ++right;
        }
      if(dist(now,a[left])>dist(now,b[right]))
        {
          s[a[left]].flag=1;
          ans+=dist(now,a[left]);
          now=getnow(now,a[left]);
        }
      else
        {
          s[b[right]].flag=1;
          ans+=dist(now,b[right]);
          now=getnow(now,b[right]);
        }
    }
  printf("%lld\n",std::max(ans+abs(now),rans));
  return 0;
}