[Codeforces] number theory (R1600) Part.8

[Codeforces] number theory (R1600) Part.8

题单:https://codeforces.com/problemset/page/1?tags=number+theory%2C1201-1600

1242A. Tile Painting

原题指路:https://codeforces.com/problemset/problem/1242/A

题意

编号1∼n1\sim n1nnnn的格子排成一行.现对这些格子染色,定义一种染色方案是好的,如果对∀i,j  (i≠j) s.t. ∣j−i∣\forall i,j\ \ (i\neq j)\ s.t.\ |j-i|i,j  (i=j) s.t. jinnn的一个>1>1>1的约数,则它们颜色相同.给定n  (1≤n≤1e12)n\ \ (1\leq n\leq 1\mathrm{e}12)n  (1n1e12),问至多能用多少种颜色染色,使得染色方案是好的.

思路

①若n=pk  (p∈primes)n=p^k\ \ (p\in primes)n=pk  (pprimes),因nnnpppppp种余数,故ans=pans=pans=p.

②若n=pq  (p,q>1)n=pq\ \ (p,q>1)n=pq  (p,q>1)gcd⁡(p,q)=1\gcd(p,q)=1gcd(p,q)=1,则ans=1ans=1ans=1.

​ [] 对∀i,j  (i≠j)\forall i,j\ \ (i\neq j)i,j  (i=j),由CRT:∃x∈[1,n] s.t. x≡i  (mod p),x≡j  (mod p)\exists x\in[1,n]\ s.t.\ x\equiv i\ \ (\mathrm{mod}\ p),x\equiv j\ \ (\mathrm{mod}\ p)x[1,n] s.t. xi  (mod p),xj  (mod p),

​ 则下标i,ji,ji,j与下标xxx颜色相同,进而所有格子颜色相同.

代码

void solve() {
  ll n; cin >> n;

  for (int d = 2; (ll)d * d <= n; d++) {
    if (n % d == 0) {
      while (n % d == 0) n /= d;
      if (n > 1) {
        cout << 1;
        return;
      }
      else {
        cout << d;
        return;
      }
    }
  }
  cout << n;
}

int main() {
  solve();
}


1263C. Everyone is a Winner!

原题指路:https://codeforces.com/problemset/problem/1263/C

题意

t  (1≤t≤10)t\ \ (1\leq t\leq 10)t  (1t10)组测试数据.每组测试数据输入一个整数n  (1≤n≤1e9)n\ \ (1\leq n\leq 1\mathrm{e}9)n  (1n1e9).对所有正整数kkk,问⌊nk⌋\left\lfloor\dfrac{n}{k}\right\rfloorkn有多少种不同的取值,第一行输出不同取值的个数,第二行升序输出所有取值.

思路

所有0≤x<⌊n⌋0\leq x<\left\lfloor\sqrt{n}\right\rfloor0x<n都是解.

[] 方程⌊nk⌋=x\left\lfloor\dfrac{n}{k}\right\rfloor=xkn=x等价于x≤nk<x+1x\leq\dfrac{n}{k}<x+1xkn<x+1,解得k∈(nx+1,nx]k\in\left(\dfrac{n}{x+1},\dfrac{n}{x}\right]k(x+1n,xn],区间长度为nx2+x\dfrac{n}{x^2+x}x2+xn.

注意到x<⌊n⌋x<\left\lfloor\sqrt{n}\right\rfloorx<n时,nx2+x>1\dfrac{n}{x^2+x}>1x2+xn>1,则区间内至少存在一个整数k=⌊nx⌋k=\left\lfloor\dfrac{n}{x}\right\rfloork=xn,故所有x∈[0,⌊n⌋)x\in\left[0,\left\lfloor\sqrt{n}\right\rfloor\right)x[0,n)都是解.

整除分块求所有解即可.

代码

void solve() {
  int n; cin >> n;

  vi ans;
  for (int l = 1, r, t; l <= n; l = r + 1) {
    r = (t = n / l) ? min(n / t, n) : n;
    ans.push_back(n / l);
  }
  ans.push_back(0);

  reverse(all(ans));  // 注意翻转
  cout << ans.size() << endl;
  for (int i : ans) cout << i << ' ';
  cout << endl;
}

int main() {
  CaseT  // 单测时注释掉该行
    solve();
}


1266C. Diverse Matrix

原题指路:https://codeforces.com/problemset/problem/1266/C

题意

AAA是一个r×cr\times cr×c的整型矩阵,其中元素未必不同.构造一个长度为(r+c)(r+c)(r+c)的序列b[]b[]b[],其中前rrr个元素是AAA每行的gcd⁡\gcdgcd,后ccc个元素是AAA每列的gcd⁡\gcdgcd.称序列b[]b[]b[]是好的,如果其中的元素两两相异.定义好的序列的权值为其中元素的最大值.

给定两整数rrrc  (1≤r,c≤500)c\ \ (1\leq r,c\leq 500)c  (1r,c500),构造一个r×cr\times cr×c矩阵AAA使得其产生的序列b[]b[]b[]是好的,且其权值最小.无解输出000.若有多组解,输出任一组解.

思路

r=c=1r=c=1r=c=1时无解.

r=1r=1r=1时,最优解为A=[2 3 ⋯ c+1]A=[2\ 3\ \cdots\ c+1]A=[2 3  c+1],不取1∼c1\sim c1c是因为111会重复.

c=1c=1c=1时,最优解为A=[2 3 ⋯ c+1]TA=[2\ 3\ \cdots\ c+1]^TA=[2 3  c+1]T.

r,c≥2r,c\geq 2r,c2时,令aij=i(j+r)a_{ij}=i(j+r)aij=i(j+r),则bi=gcd⁡{i(r+1),⋯ ,i(r+c)}=i⋅gcd⁡{r+1,⋯ ,r+c}=ib_i=\gcd\{i(r+1),\cdots,i(r+c)\}=i\cdot \gcd\{r+1,\cdots,r+c\}=ibi=gcd{i(r+1),,i(r+c)}=igcd{r+1,,r+c}=i.

​ 此时b[]b[]b[]的权值为(r+c)(r+c)(r+c),显然这是最小的.

代码

void solve() {
  int r, c; cin >> r >> c;

  if (r * c == 1) {
    cout << 0;
    return;
  }

  if (r == 1) {
    for (int i = 2; i <= c + 1; i++) cout << i << ' ';
    return;
  }
  else if (c == 1) {
    for (int i = 2; i <= r + 1; i++) cout << i << endl;
    return;
  }

  for (int i = 1; i <= r; i++)
    for (int j = 1; j <= c; j++) cout << i * (j + r) << " \n"[j == c];
}

int main() {
  solve();
}


1285C. Fadi and LCM

原题指路:https://codeforces.com/problemset/problem/1285/C

题意

给定一个整数x  (1≤x≤1e12)x\ \ (1\leq x\leq 1\mathrm{e}12)x  (1x1e12),求两正整数a,b s.t. lcm(a,b)=xa,b\ s.t.\ \mathrm{lcm}(a,b)=xa,b s.t. lcm(a,b)=xmax⁡{a,b}\max\{a,b\}max{a,b}最小.若有多组解,输出任一组.

思路I

xxx素因数分解后,枚举将素因子分配给aaabbb的所有方案,求max⁡{a,b}\max\{a,b\}max{a,b}的最小值.

代码I

vl factors;

void get(ll n) {  // 对x素因数分解
  for (ll d = 2; d * d <= n; d++) {
    if (n % d == 0) {
      ll cur = 1;
      while (n % d == 0) n /= d, cur *= d;
      factors.push_back(cur);
    }
  }
  if (n > 1) factors.push_back(n);
}

void solve() {
  ll x; cin >> x;

  get(x);

  ll ansa = INFF, ansb = INFF;
  int n = factors.size();
  for (int i = 0; i < (1 << n); i++) {
    ll a = 1, b = 1;
    for (int j = 0; j < n; j++) {
      if (i >> j & 1) a *= factors[j];
      else b *= factors[j];
    }

    if (max(a, b) < max(ansa, ansb)) ansa = a, ansb = b;
  }
  cout << ansa << ' ' << ansb;
}

int main() {
  solve();
}

思路II

枚举xxx的约数ddd,检查是否有lcm(d,xd)=x\mathrm{lcm}\left(d,\dfrac{x}{d}\right)=xlcm(d,dx)=x,更新max⁡{a,b}\max\{a,b\}max{a,b}的最小值.

代码II

void solve() {
  ll x; cin >> x;

  ll ans = 0;
  for (ll d = 1; d * d <= x; d++) 
    if (x % d == 0 && lcm(d, x / d) == x) ans = d;
  cout << ans << ' ' << x / ans;
}

int main() {
    solve();
}


1294C. Product of Three Numbers

原题指路:https://codeforces.com/problemset/problem/1294/C

题意 (2 s)(2\ \mathrm{s})(2 s)

t  (1≤t≤100)t\ \ (1\leq t\leq 100)t  (1t100)组测试数据.每组测试数据输入一个整数n  (2≤n≤1e9)n\ \ (2\leq n\leq 1\mathrm{e}9)n  (2n1e9).求三个相异的正整数a,b,c s.t. a,b,c≥2a,b,c\ s.t.\ a,b,c\geq 2a,b,c s.t. a,b,c2n=abcn=abcn=abc,若有解则第一行输出"YES",第二行输出任一组解;否则输出"NO".

思路

不妨设a<b<ca<b<ca<b<c,下面最小化aaa并最大化ccc.设aaannn>1>1>1的最小约数,bbbna\dfrac{n}{a}an的非aaa>1>1>1的最小约数,若nab≠a,b,1\dfrac{n}{ab}\neq a,b,1abn=a,b,1,则找到一组解.

代码

void solve() {
  int n; cin >> n;

  uset<int> s;
  for (int d = 2; (ll)d * d <= n; d++) {  // 求n的>1的最小约数a
    if (n % d == 0) {
      n /= d;
      s.insert(d);
      break;
    }
  }
  for (int d = 2; (ll)d * d <= n; d++) {  // 求n/a的非a的>1的最小约数b
    if (n % d == 0 && !s.count(d)) {
      n /= d;
      s.insert(d);
      break;
    }
  }

  if (s.size() < 2 || s.count(n) || n == 1) cout << "NO" << endl;
  else {
    cout << "YES" << endl;
    s.insert(n);
    for (auto i : s) cout << i << ' ';
    cout << endl;
  }
}

int main() {
  CaseT  // 单测时注释掉该行
    solve();
}


1305C. Kuroni and Impossible Calculation

原题指路:https://codeforces.com/problemset/problem/1305/C

题意

给定一个长度为n  (2≤n≤2e5)n\ \ (2\leq n\leq 2\mathrm{e}5)n  (2n2e5)的序列a1,⋯ ,an  (0≤ai≤1e9)a_1,\cdots,a_n\ \ (0\leq a_i\leq 1\mathrm{e}9)a1,,an  (0ai1e9)和一个整数m  (1≤m≤1000)m\ \ (1\leq m\leq 1000)m  (1m1000),求∏1≤i<j≤n∣ai−aj∣\displaystyle \prod_{1\leq i<j\leq n}|a_i-a_j|1i<jnaiaj,答案对mmm取模.

思路

n≤mn\leq mnm时,暴力求即可.

n>mn>mn>m时,因模mmm只有mmm种余数,则至少存在两个数ai,aj s.t. ai≡aj  (mod m)a_i,a_j\ s.t.\ a_i\equiv a_j\ \ (\mathrm{mod}\ m)ai,aj s.t. aiaj  (mod m),故ans=0ans=0ans=0.

代码

void solve() {
  int n, m; cin >> n >> m;
  vi a(n);
  for (auto& ai : a) cin >> ai;

  if (n > m) cout << 0;
  else {
    int ans = 1;
    for (int i = 0; i < n; i++)
      for (int j = i + 1; j < n; j++) ans = (ll)abs(a[i] - a[j]) % m * ans % m;
    cout << ans;
  }
}

int main() {
  solve();
}


1312C. Adding Powers

原题指路:https://codeforces.com/problemset/problem/1312/C

题意 (2 s2\ \mathrm{s}2 s)

序列v1,⋯ ,vnv_1,\cdots,v_nv1,,vn初始时都为零.现有操作:在第iii步(下标从000开始)时,可选择跳过此步,也可选择一个下标pos∈[1,n]pos\in[1,n]pos[1,n],令vpos+=kiv_{pos}+=k^ivpos+=ki.给定一个序列a1,⋯ ,ana_1,\cdots,a_na1,,an,问若干次操作后能否将序列v[]v[]v[]变为序列a[]a[]a[],若能则输出"YES";否则输出"NO".

t  (1≤t≤1000)t\ \ (1\leq t\leq 1000)t  (1t1000)组测试数据.每组测试数据第一行输入两个整数n,k  (1≤n≤30,2≤k≤100)n,k\ \ (1\leq n\leq 30,2\leq k\leq 100)n,k  (1n30,2k100).第二行输入nnn个整数a1,⋯ ,an  (0≤ai≤1e16)a_1,\cdots,a_n\ \ (0\leq a_i\leq 1\mathrm{e}16)a1,,an  (0ai1e16).

思路

将每个aia_iai表示成kkk进制数,检查是否有相同的kkk的幂次.

代码

const int MAXN = 35;
int n, k;
ll a[MAXN];

bool check() {
  uset<int> s;  // 记录用过的k的幂次
  for (int i = 0; i < n; i++) {
    ll x = a[i];
    int d = 0;  // k的幂次
    while (x) {
      if (x % k != 0 && x % k != 1) return false;

      if (x % k == 1) {
        if (s.count(d)) return false;
        s.insert(d);
      }
      d++;
      x /= k;
    }
  }
  return true;
}

void solve() {
  cin >> n >> k;
  for (int i = 0; i < n; i++) cin >> a[i];

  cout << (check() ? "YES" : "NO") << endl;    
}

int main() {
  CaseT  // 单测时注释掉该行
    solve();
}


1332B. Composite Coloring

原题指路:https://codeforces.com/problemset/problem/1332/B

题意 (2 s)(2\ \mathrm{s})(2 s)

称一个正整数是好的,如果它能表示为两>1>1>1的正整数之积.称一个序列是好的,如果其所有元素都是好的.

给定一个长度为nnn的好的序列a1,⋯ ,ana_1,\cdots,a_na1,,an.现选定一个正整数m∈[1,m]m\in[1,m]m[1,m],用编号1∼m1\sim m1mmmm种颜色给序列染色,使得每种颜色至少用一次,序列中每个元素被染有且只有一种颜色,任意两个相同颜色的元素的gcd⁡>1\gcd>1gcd>1.注意相等的元素可染不同色.可以证明当所有ai≤1000a_i\leq 1000ai1000时有解.构造任一组染色方案,第一行输出所用颜色的种数,第二行输出一个染色方案.

t  (1≤t≤1000)t\ \ (1\leq t\leq 1000)t  (1t1000)组测试数据.每组测试数据第一行输入一个整数n  (1≤n≤1000)n\ \ (1\leq n\leq 1000)n  (1n1000).第二行输入一个长度为nnn的好的序列a1,⋯ ,an  (4≤ai≤1000)a_1,\cdots,a_n\ \ (4\leq a_i\leq 1000)a1,,an  (4ai1000).数据保证所有测试数据的nnn之和不超过1e41\mathrm{e}41e4.

思路

对每个好的数kkk,存在一个素数p≤k s.t. p∣kp\leq \sqrt{k}\ s.t.\ p\mid kpk s.t. pk.因1000\sqrt{1000}1000以内共111111个素数,则每个数与其素因子染相同颜色即可.

代码

const int MAXN = 1005;
vi res[MAXN];  // 含有最小素因子p的元素的下标
int ans[MAXN];

int get(int x) {  // 求x的最小素因子
  for (int i = 2; i * i <= x; i++)
    if (x % i == 0) return i;
  return x;
}

void solve() {
  int n; cin >> n;
  for (int i = 1; i < MAXN; i++) res[i].clear();

  for (int i = 1; i <= n; i++) {
    int a; cin >> a;
    res[get(a)].push_back(i);
  }

  int color = 0;
  for (int i = 1; i < MAXN; i++) {
    if (res[i].size()) {
      color++;
      for (auto j : res[i]) ans[j] = color;
    }
  }

  cout << color << endl;
  for (int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];
}

int main() {
  CaseT  // 单测时注释掉该行
    solve();
}


1342C. Yet Another Counting Problem

原题指路:https://codeforces.com/problemset/problem/1342/C

题意 (3.5 s)(3.5\ \mathrm{s})(3.5 s)

给定两整数a,ba,ba,b.现给定两整数l,rl,rl,r,表示询问有多少个x∈[l,r] s.t. (x mod a) mod b≠(x mod b) mod ax\in[l,r]\ s.t.\ (x\ \mathrm{mod}\ a)\ \mathrm{mod}\ b\neq (x\ \mathrm{mod}\ b)\ \mathrm{mod}\ ax[l,r] s.t. (x mod a) mod b=(x mod b) mod a.

t  (1≤t≤100)t\ \ (1\leq t\leq 100)t  (1t100)组测试数据.每组测试数据第一行输入三个整数a,b,q  (1≤a,b≤200,1≤q≤500)a,b,q\ \ (1\leq a,b\leq 200,1\leq q\leq 500)a,b,q  (1a,b200,1q500),其中qqq表示询问书.接下来qqq行每行输入两个整数l,r  (1≤l≤r≤1e18)l,r\ \ (1\leq l\leq r\leq 1\mathrm{e}18)l,r  (1lr1e18),表示一个询问.

思路

注意到[(x+ab) mod a] mod b=(x mod a) mod b[(x+ab)\ \mathrm{mod}\ a]\ \mathrm{mod}\ b=(x\ \mathrm{mod}\ a)\ \mathrm{mod}\ b[(x+ab) mod a] mod b=(x mod a) mod b,则xxx有上述性质当且仅当x mod abx\ \mathrm{mod}\ abx mod ab有上述性质.

预处理出len=ablen=ablen=ab内满足所需性质的数的个数的前缀和pre[]pre[]pre[],根据⌊xlen⌋\left\lfloor\dfrac{x}{len}\right\rfloorlenxx%lenx\% lenx%len[1,x][1,x][1,x]中有多少个数满足所需性质.

代码

const int MAXN = 4e4 + 5;
int pre[MAXN];  // 满足所需性质的数的个数的前缀和
int len;  // a*b

void init(int a,int b) {
  len = a * b;
  for (int i = 1; i <= len; i++) 
    pre[i] = pre[i - 1] + ((i % a) % b != (i % b) % a);
}

ll query(ll x) {
  ll cnt = x / len, rest = x % len;
  return cnt * pre[len] + pre[rest];
}

ll query(ll l, ll r) {
  return query(r) - query(l - 1);
}

void solve() {
  int a, b; cin >> a >> b;
  init(a, b);

  CaseT{
    ll l, r; cin >> l >> r;
    cout << query(l, r) << ' ';
  }
  cout << endl;
}

int main() {
  CaseT  // 单测时注释掉该行
    solve();
}


1344A. Hilbert’s Hotel

原题指路:https://codeforces.com/problemset/problem/1344/A

题意

有无限个房间,其中编号0∼(n−1)0\sim (n-1)0(n1)nnn个房间分别住着客人a0,⋯ ,an−1a_0,\cdots,a_{n-1}a0,,an1.现有操作:对每个整数k∈[0,k−1]k\in[0,k-1]k[0,k1],将kkk号房间的客人移动到(k+ak mod n)(k+a_{k\ \mathrm{mod}\ n})(k+ak mod n)号房间.问操作后0∼(n−1)0\sim (n-1)0(n1)号房间是否有且只有一个客人.

t  (1≤t≤1e4)t\ \ (1\leq t\leq 1\mathrm{e}4)t  (1t1e4)组测试数据.每组测试数据第一行输入一个整数n  (1≤n≤2e5)n\ \ (1\leq n\leq 2\mathrm{e}5)n  (1n2e5).第二行输入一个长度为nnn的序列a0⋯ ,an−1  (−1e9≤ai≤1e9)a_0\cdots,a_{n-1}\ \ (-1\mathrm{e}9\leq a_i\leq 1\mathrm{e}9)a0,an1  (1e9ai1e9).数据保证所有测试数据的nnn之和不超过2e52\mathrm{e}52e5.

思路

0∼(n−1)0\sim (n-1)0(n1)号房间是否有且只有一个客人等价于没有两个客人在同一房间且没有空房间.

设操作后存在两个客人在同一房间,则x+ax mod n=y+ay mod nx+a_{x\ \mathrm{mod}\ n}=y+a_{y\ \mathrm{mod}\ n}x+ax mod n=y+ay mod n至少有一整数解.

x=k1n+i,y=k2n+jx=k_1n+i,y=k_2n+jx=k1n+i,y=k2n+j,则原方程⇔x−y=ay mod n−ax mod n⇔k1n+i−k2n−j=aj−ai\Leftrightarrow x-y=a_{y\ \mathrm{mod}\ n}-a_{x\ \mathrm{mod}\ n}\Leftrightarrow k_1n+i-k_2n-j=a_j-a_ixy=ay mod nax mod nk1n+ik2nj=ajai,

(k1−k2)n=aj−ai+j−i=(aj+j)−(ai+i)(k_1-k_2)n=a_j-a_i+j-i=(a_j+j)-(a_i+i)(k1k2)n=ajai+ji=(aj+j)(ai+i).

bi=ai+ib_i=a_i+ibi=ai+i,则等价于求(k1−k2)n=cj−ci(k_1-k_2)n=c_j-c_i(k1k2)n=cjci的正整数解ci,cjc_i,c_jci,cj,显然这等价于ci≡cj  (mod n)c_i\equiv c_j\ \ (\mathrm{mod}\ n)cicj  (mod n).

预处理出所有(i+ai) mod n(i+a_i)\ \mathrm{mod}\ n(i+ai) mod n,检查余数是否为0∼(n−1)0\sim (n-1)0(n1)即可.

代码

void solve() {
  int n; cin >> n;
  vi a(n);
  for (int i = 0; i < n; i++) {
    cin >> a[i];
    a[i] = ((i + a[i]) % n + n) % n;
  }

  sort(all(a));
  bool ok = true;
  for (int i = 0; i < n; i++) ok &= a[i] == i;
  cout << (ok ? "YES" : "NO") << endl;
}

int main() {
  CaseT  // 单测时注释掉该行
    solve();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值