C. Almost All Multiples

C. Almost All Multiples

Given two integers n and x, a permutation p of length n is called funny if pi is a multiple of i for all 1in1, pn=1, and p1=x.

Find the lexicographically minimal funny permutation, or report that no such permutation exists.

A permutation of length n is an array consisting of each of the integers from 1 to n exactly once.

Let a and b be permutations of length n. Then a is lexicographically smaller than b if in the first position i where a and b differ, ai<bi. A permutation is lexicographically minimal if it is lexicographically smaller than all other permutations.

Input

The input consists of multiple test cases. The first line contains an integer t (1t104) — the number of test cases. The description of the test cases follows.

The only line of each test case contains two integers n and x (2n2105; 1<xn).

The sum of n across all test cases does not exceed 2105.

Output

For each test case, if the answer exists, output n distinct integers p1,p2,,pn (1pin) — the lexicographically minimal funny permutation p. Otherwise, output 1.

Example

input

3
3 3
4 2
5 4

output

3 2 1 
2 4 3 1 
-1

Note

In the first test case, the permutation [3,2,1] satisfies all the conditions: p1=3, p3=1, and:

  • p1=3 is a multiple of 1.
  • p2=2 is a multiple of 2.

In the second test case, the permutation [2,4,3,1] satisfies all the conditions: p1=2, p4=1, and:

  • p1=2 is a multiple of 1.
  • p2=4 is a multiple of 2.
  • p3=3 is a multiple of 3.

We can show that these permutations are lexicographically minimal.

No such permutations exist in the third test case.

 

解题思路

  首先序列a={1,2,,n}(即ai=i)是满足条件的,现在交换一下a1an,那么序列就变成了a={n,2,3,,n1,1},也是满足条件的。当我们选择下标x,交换a1ax(也就是把n换到了下标x的位置),这时如果有nx,那么得到的序列还是满足条件的(不一定是字典序最小)。如果nx,那么我们要往后找到一个x的倍数放到x这个位置,这个数可以是kx (2knx),同理,如果选择了kx,那么还需要往后找到一个kx的倍数放到kx这个位置,以此类推,最终要把n放到某个位置,由于最后这个位置也是x的倍数,又因为这个位置不能整除nn不包含因子x),因此无解。

  对于有解的情况为了得到字典序最小,我们可以先让ax=n,然后往后遍历找x的第一个倍数(也就是2x),然后交换axa2x,此时我们应该往后找到2x的第一个倍数(也就是4x),然后交换交换a2xa4x,以此类推,直到无法交换为止。

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 2e5 + 10;
 5 
 6 int a[N];
 7 
 8 void solve() {
 9     int n, m;
10     scanf("%d %d", &n, &m);
11     if (n % m) {
12         printf("-1\n");
13         return;
14     }
15     a[1] = m, a[n] = 1;
16     for (int i = 2; i < n; i++) {
17         a[i] = i;
18     }
19     if (n != m) a[m] = n;    // 如果a[1]=n那么已经是字典序最小了
20     for (int i = m + m, j = m; i < n; i += j) {    // 当前放n的位置为j,因此要找j的倍数,即i+=j
21         if (n % i == 0) {    // n可以放到i这个位置
22             swap(a[i], a[j]);
23             j = i;
24         }
25     }
26     for (int i = 1; i <= n; i++) {
27         printf("%d ", a[i]);
28     }
29     printf("\n");
30 }
31 
32 int main() {
33     int t;
34     scanf("%d", &t);
35     while (t--) {
36         solve();
37     }
38     
39     return 0;
40 }
复制代码

  补充另外一种做法。

  对于xn,一定是无解的。假设n放置在任意一个合法的下标位置(也就是n是所在下标位置的倍数),那么这个位置原本的数就应该放置在前面某个合法位置,以此类推。可以发现在这个过程中被换出来的数都是n的因子,不可能是x的倍数(如果存在某个因子是x的倍数那么n也是x的倍数,就矛盾了)。到最后必然会置换出一个质数然后这个质数就没地方放了(如果不是质数的话说明质因数分解会得到两个以上的质数的乘积,说明前面还存在这个数的因子,可以继续往前置换)。

  因此对于有解的情况,此时下标位置x空出来,为了得到字典序最小的序列,假设质因数分解nx=P1α1P2α2Pkαk,由于n只能放在xP1β1P2β2Pkβk (0βiαi,1ik)的位置上,因此我们只能从小到大把这些数往前移一个位置,最后把n放在xP1α1P2α2Pkαk1 这个位置上。

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 2e5 + 10;
 5 
 6 int a[N];
 7 
 8 void solve() {
 9     int n, m;
10     scanf("%d %d", &n, &m);
11     if (n % m) {
12         printf("-1\n");
13         return;
14     }
15     a[1] = m, a[n] = 1;
16     for (int i = 2; i < n; i++) {
17         a[i] = i;
18     }
19     vector<int> fs;
20     int t = n / m;
21     for (int i = 2; i <= t / i; i++) {
22         while (t % i == 0) {
23             fs.push_back(i);
24             t /= i;
25         }
26     }
27     if (t > 1) fs.push_back(t);
28     for (int i = 0, j = m; i < fs.size(); i++) {
29         a[j] = j * fs[i];
30         j *= fs[i];
31     }
32     for (int i = 1; i <= n; i++) {
33         printf("%d ", a[i]);
34     }
35     printf("\n");
36 }
37 
38 int main() {
39     int t;
40     scanf("%d", &t);
41     while (t--) {
42         solve();
43     }
44     
45     return 0;
46 }
复制代码

 

参考资料

  Codeforces Round #836 (Div. 2) Editorial:https://codeforces.com/blog/entry/109438

  Codeforces Round #836 (Div. 2) A-D :https://www.cnblogs.com/BlankYang/p/16928287.html

posted @   onlyblues  阅读(106)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2021-11-26 关于KMP算法中模式串的移动不会产生漏解的证明
Web Analytics
点击右上角即可分享
微信分享提示