ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AtCoder Beginner Contest 230 A ~ G 题解

2021-12-12 04:01:42  阅读:250  来源: 互联网

标签:AtCoder cur int 题解 ll cin res 230 sum


AtCoder Beginner Contest 230 A ~ G 题解

A. AtCoder Quiz 3

按题目要求输出就行

void solve() {
  int a;
  cin >> a;
  if (a >= 42) ++a;
  printf("AGC%03d", a);
}

B. Triple Metre

就加长一下然后find就好了

void solve() {
  string s;
  for (int i = 0; i < 10; ++i) {
    s += "oxx";
  }
  string ss;
  cin >> ss;
  cout << (s.find(ss) != s.npos ? "Yes" : "No");
}

C. X drawing

判断一下在不在线上就好了,我的写法蠢了...

#define ll __int128_t
 
unsigned long long n, a, b, p, q, r, s;
ll la, lb, ra, rb, la2, ra2, lb2, rb2;
 
ll f1(ll x, ll y) {
  return (rb - lb) * x + (la - ra) * y + ra * lb - la * rb;
}
 
ll f2(ll x, ll y) {
  return (rb2 - lb2) * x + (la2 - ra2) * y + ra2 * lb2 - la2 * rb2;
}
 
void solve() {
  cin >> n >> a >> b;
  cin >> p >> q >> r >> s;
  ll kn1 = min(1 - a, 1 - b), km1 = max(n - a, n - b);
  la = a + kn1, ra = a + km1;
  lb = b + kn1, rb = b + km1;
  ll kn2 = max(1 - a, b - n), km2 = min(n - a, b - 1);
  la2 = a + kn2, ra2 = a + km2;
  lb2 = b - kn2, rb2 = b - km2;
  for (ll i = p; i <= q; ++i) {
    for (ll j = r; j <= s; ++j) {
      if (f1(i, j) == 0 || f2(i, j) == 0) {
        cout << '#';
      }
      else {
        cout << '.';
      }
    }
    cout << '\n';
  }
}

因为变成int128前还加了一次直接爆了wa了两个点导致多debug了半小时...

反正我这写法很纯就是了但是题目也看不太懂就没有想太深

D. Destroyer Takahashi

就经典的贪心板子排个序贪就完事了

struct node {
  ll l, r;
  bool operator < (const node &a) {
    if (r == a.r) {
      return l > a.l;
    }
    return r <= a.r;
  }
} range[N];
 
void solve() {
  ll n, d;
  cin >> n >> d;
  for (int i = 0; i < n; ++i) {
    cin >> range[i].l >> range[i].r;
  }
  ll ans = 0, ed = -2e9;
  sort(range, range + n);
  for (int i = 0; i < n; ++i) {
    if (range[i].l > ed) {
      ++ans;
      ed = range[i].r + d - 1;
    }
  }
  cout << ans;
}

E. Fraction Floor Sum

经典的数论分块板子也不用被名词吓到,就是枚举值域考虑对这个值域有多少个数可以贡献然后算就好了,说不定有人可以因为这题自己发明数论分块(,我以前打abc的时候就有道最小生成树的板题但我还不知道kruskal最小生成树,然后自己用并查集加贪心把那道题写出来,还是挺有趣的

void solve() {
  ll n;
  cin >> n;
  ll ans = 0;
  for(ll l = 1 , r; l <= n; l = r + 1) {
	  r = n / (n / l);
	  ans += (r - l + 1) * (n / l);
  }
  cout << ans;
}

F. Predilection

F很妙很妙

属于是不看题解基本不可能做出来的dp

dp也是我的弱项还是需要提高

f就是每一个前缀和最后出现的一次是多少

sum就是每一个前缀和的f值加起来

res就是记录前缀和

cur就是每一个fi值应该是多少

先把前缀和算出来,当前不同前缀和加起来显然也就是sum

如果前缀和是0那就有全部都消失的情况所以要++cur

res上一次出现的f值应该减

然后f[res]现在是cur所以要把cur加到sum

如果所有数都是0就得把非法情况减掉

int a[N];

void solve() {
  int n;
  cin >> n;
  for (int i = 1; i <= n; ++i) cin >> a[i];
  int sum = 1, cur;
  ll res = 0;
  map<ll, int> f;
  f[0] = 1;
  for (int i = 1; i <= n; ++i) {
    res += a[i];
    cur = sum;
    if (res == 0) ++cur;
    if (cur >= mod) cur -= mod;
    sum -= f[res];
    if (sum < 0) sum += mod;
    f[res] = cur;
    sum += f[res];  
    if (sum >= mod) sum -= mod;
  }
  if (res == 0) --cur;
  cout << cur;
}

G. GCD Permutation

这题还是很有趣的

莫比乌斯函数可以看作是一种容斥,容斥过程中 mu[i] 不为 0 才有效

然后这题先找位置然后再找位置上的数就可以做出来了

初始化先mu筛出来,然后再把i的因子筛出来

然后枚举位置的gcd如果有效就把倍数都加进来然后把莫比乌斯函数的值作为系数乘上每个数的因子乘上有多少个数是他的倍数并且可以重复取然后计算贡献就好了。

int mu[N], pr[N], a[N], sz[N];
bool vis[N];
vector<int> v[N];
map<int, int> mp;
int num, tot;
 
void shai() {
  mu[1] = 1;
  for (int i = 2; i <= 200000; ++i) {
    if (!vis[i]) {
      pr[++tot] = i;
      mu[i] = -1;
    }
    for (int j = 1; j <= tot && i * pr[j] <= 200000; ++j) {
      vis[i * pr[j]] = 1;
      if (i % pr[j]) mu[i * pr[j]] = -mu[i];
      else {
        mu[i * pr[j]] = 0;
        break;
      }
    }
  }
 
  for (int i = 2; i <= 200000; ++i) {
    for (int j = 2; j <= i / j; ++j) {
      if (i % j == 0) {
        if (mu[j]) {
          v[i].push_back(j);
        }
        if (mu[i / j] && (j * j != i)) {
          v[i].push_back(i / j);
        }
      }
    }
    if (mu[i]) {
      v[i].push_back(i);
    }
  }
}
 
ll calc() {
  mp.clear();
  ll res = 0;
  for (int i = 1; i <= num; ++i) {
    for (auto & j : v[sz[i]]) {
      mp[j]++;
    }
  }
  for (auto & i : mp) {
    res += 1ll * -mu[i.first] * i.second *(i.second + 1) / 2;
  }
  return res;
}
 
void solve() {
  int n;
  cin >> n;
  for (int i = 1; i <= n; ++i) cin >> a[i];
  shai();
  ll ans = 0;
  for (int i = 2; i <= n; ++i) {
    if (mu[i]) {
      num = 0;
      for (int j = i; j <= n; j += i) {
        sz[++num] = a[j];
      }
      ans += -mu[i] * calc();
    }
  }
  cout << ans;
}

标签:AtCoder,cur,int,题解,ll,cin,res,230,sum
来源: https://www.cnblogs.com/empathy/p/15678056.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有