CodeTON Round 9 (Div. 1 + Div. 2) C1C2解题

C1

题意

给定两个整数 x , m x, m x,m,求 y y y的个数。 y y y满足 1 ≤ y ≤ m , x ≠ y 1 \leq y \leq m, x \neq y 1ym,x=y, x ⊕ y x \oplus y xy是x或y的因数。

思路

先说结论:

c = x ⊕ y c = x \oplus y c=xy
1 ≤ y ≤ m , y ≤ 2 x , c ≤ y 2 ≤ x 1 \leq y \leq m, y \leq 2x, c \leq \frac{y}{2} \leq x 1ym,y2x,c2yx
由于 x , m x, m x,m大小关系不确定,因此 1 ≤ c ≤ m i n ( x , m ) 1 \leq c \leq min(x, m) 1cmin(x,m)
遍历c逐个判断即可。

证明:

c = x ⊕ y c = x \oplus y c=xy,答案即为求满足 c c c是x或y的因数的 c c c的个数。

  • 如果 p p p q q q的因数,且 p ≠ q p\neq q p=q,则 p ≤ q 2 p \leq \frac{q}{2} p2q
    x ≠ y x \neq y x=y,则 c ≠ 0 c \neq 0 c=0
    y ≠ 0 y \neq 0 y=0, 则 c ≠ x c \neq x c=x
    因此 c ≤ x 2 c \leq \frac{x}{2} c2x c ≤ y 2 c \leq \frac{y}{2} c2y
  • 如果x与y的最高位不一样(可以取 y ≥ 2 x y \geq 2x y2x),则 x ⊕ y x \oplus y xy的二进制最高位是1, x ⊕ y x \oplus y xy不可能是x或y的因数。 因此 y ≤ 2 x y \leq 2x y2x
    例如:
110010110
011011110

1 ≤ y ≤ m , y ≤ 2 x , c ≤ y 2 ≤ x 1 \leq y \leq m, y \leq 2x, c \leq \frac{y}{2} \leq x 1ym,y2x,c2yx
由于 x , m x, m x,m大小关系不确定,因此 1 ≤ c ≤ m i n ( x , m ) 1 \leq c \leq min(x, m) 1cmin(x,m)

解题

#include   
  
using namespace std;  
typedef long long ll;  
#define FKCF ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);  
#define dbg(x) cout<<"[debug] "<<#x<<" = "<<x<<endl;  
// ============ BEGIN ============ //  
  
inline void solve(){  
    ll x, m;  
    int cnt=0;  
    cin >> x >> m;  
    // 设 c = x ^ y    
    for (int c = 1ll; c <= (int)min(x, m); ++c) {  
        ll y = c ^ x;  
        if ((!(x % c) || !(y % c)) && x != y && y && y <= m) ++cnt;  
  
    }  
    cout << cnt << endl;  
}  
  
int main() {  
    FKCF  
    int t;  
    cin >> t;  
  
    while (t--) {  
        solve();  
    }  
    return 0;  
}

C2

题意:

给定两个整数 x , m x, m x,m,求 y y y的个数。 y y y满足 1 ≤ y ≤ m 1 \leq y \leq m 1ym x ⊕ y x \oplus y xy x x x y y y的因数(包括0)。

思路:

c = x ⊕ y c = x \oplus y c=xy
和上一题一样,以计数c代替计数y。

1. 求c是x的因数 的个数
p是c满足y范围内能取到的最后一个c。即 p = m − m % x p = m - m \% x p=mm%x
a n s = p x ans = \frac{p}{x} ans=xp

  ll p = m - m % x;
  ll ans = p / x - (x < p); // c=x无法取到,c=0必取到
  // y = x ^ p
  // 考虑c能否取到p
  if ((x ^ p) >= 1 and (x ^ p) <= m) ++ans;
  p += x;
  // 考虑c能否取到p+x
  if ((x ^ p) >= 1 and (x ^ p) <= m) ++ans;

2. 求c是y的因数 的个数
y > x y>x y>x c c c不再可能是y的因数。原因见上一题。

for (int y = 1; y <= min(1LL * x, m); y++) {  
    ll c = x ^ y;  
    if (c % y == 0) {  
        ++ans;  
    }  
}

3. 求c是x,y的因数 的个数
需使 c = l c m ( x , y ) c=lcm(x, y) c=lcm(x,y)
y = x y=x y=x,即 c = 0 c=0 c=0

if (x <= m) {  
    --ans;  
}

解题

#include   
  
using namespace std;  
typedef long long ll;  
#define CF ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);  
#define dbg(x) cout<<"[debug] "<<#x<<" = "<<x<<endl;  
// ============ BEGIN ============ //  
  
void solve() {  
    int x; ll m; cin >> x >> m;  
  
    // divisible by x  
    ll p = m - m % x;  
    ll ans = p / x - (x < p);  
    if ((x ^ p) >= 1 and (x ^ p) <= m) ++ans;  
    p += x;  
    if ((x ^ p) >= 1 and (x ^ p) <= m) ++ans;  
  
    // divisibly by y  
    for (int y = 1; y <= min(1LL * x, m); y++) {  
        ll cur = x ^ y;  
        if (cur % y == 0) {  
            ++ans;  
        }  
    }  
  
    // divisible by both  
    if (x <= m) {  
        --ans;  
    }  
  
    cout << ans << '\n';  
}  
  
int32_t main() {  
    CF  
    int t = 1;  
    cin >> t;  
    while (t--) solve();  
      
    return 0;  
}

你可能感兴趣的:(Codeforces,算法)