AtCoder Beginner Contest 161 比赛人数9927 快,比赛开始后5分钟看到所有题
AtCoder Beginner Contest 161 F Division or Substraction 打表+找规律+数论
总目录详见https://blog.csdn.net/mrcrack/article/details/104454762
在线测评地址https://atcoder.jp/contests/abc161/tasks/abc161_f
样例模拟如下
6
3
2:6/2=3,3-2=1选
3:6/3=2不选
4:6-4=2不选
5:6-5=1选
6:6/6=1选
为了获得更多的数据,编写了打表代码,如下
#include <stdio.h>
#define LL long long
int judge(LL x,LL n){
while(n>=x){
if(n%x==0)n/=x;
else n-=x;
}
if(n==1)return 1;
else return 0;
}
int main(){
LL i,n,k,j;
scanf("%lld",&n);
for(i=2;i<=n;i++){
printf("%lld\n",i);
for(j=2;j<=i;j++)
if(judge(j,i))printf("%lld ",j);
printf("\n\n");
}
return 0;
}
编译上述打表代码,运行,输入100,获得了输出数据如下
2
2
3
2 3
4
2 3 4
5
2 4 5
6
2 5 6
7
2 3 6 7
8
2 7 8
9
2 3 4 8 9
10
2 3 9 10
11
2 5 10 11
12
2 3 11 12
13
2 3 4 6 12 13
14
2 13 14
15
2 7 14 15
16
2 3 4 5 15 16
17
2 4 8 16 17
18
2 17 18
19
2 3 6 9 18 19
20
2 4 19 20
21
2 3 4 5 10 20 21
22
2 3 7 21 22
23
2 11 22 23
24
2 23 24
25
2 3 4 5 6 8 12 24 25
26
2 5 25 26
27
2 3 13 26 27
28
2 3 9 27 28
29
2 4 7 14 28 29
30
2 3 5 29 30
31
2 3 5 6 10 15 30 31
32
2 31 32
33
2 4 8 16 32 33
34
2 3 11 33 34
35
2 17 34 35
36
2 3 4 5 6 7 35 36
37
2 3 4 6 9 12 18 36 37
38
2 37 38
39
2 3 19 38 39
40
2 3 13 39 40
41
2 4 5 8 10 20 40 41
42
2 6 41 42
43
2 3 6 7 14 21 42 43
44
2 43 44
45
2 4 11 22 44 45
46
2 3 5 9 15 45 46
47
2 23 46 47
48
2 3 47 48
49
2 3 4 6 7 8 12 16 24 48 49
50
2 7 49 50
51
2 5 10 25 50 51
52
2 3 4 17 51 52
53
2 4 13 26 52 53
54
2 53 54
55
2 3 5 6 9 18 27 54 55
56
2 5 7 11 55 56
57
2 3 4 7 8 14 28 56 57
58
2 3 19 57 58
59
2 29 58 59
60
2 59 60
61
2 3 4 5 6 10 12 15 20 30 60 61
62
2 61 62
63
2 3 31 62 63
64
2 3 4 7 8 9 21 63 64
65
2 4 8 16 32 64 65
66
2 3 5 13 65 66
67
2 3 6 11 22 33 66 67
68
2 4 67 68
69
2 4 17 34 68 69
70
2 3 23 69 70
71
2 5 7 10 14 35 70 71
72
2 8 71 72
73
2 3 4 6 8 9 12 18 24 36 72 73
74
2 73 74
75
2 3 37 74 75
76
2 3 5 15 25 75 76
77
2 4 19 38 76 77
78
2 6 7 11 77 78
79
2 3 6 13 26 39 78 79
80
2 4 5 79 80
81
2 3 4 5 8 9 10 16 20 40 80 81
82
2 3 9 27 81 82
83
2 41 82 83
84
2 3 4 83 84
85
2 3 4 6 7 12 14 21 28 42 84 85
86
2 5 17 85 86
87
2 43 86 87
88
2 3 29 87 88
89
2 4 8 11 22 44 88 89
90
2 3 9 89 90
91
2 3 5 6 9 10 15 18 30 45 90 91
92
2 7 13 91 92
93
2 3 4 23 46 92 93
94
2 3 31 93 94
95
2 47 94 95
96
2 5 19 95 96
97
2 3 4 6 8 12 16 24 32 48 96 97
98
2 97 98
99
2 7 14 49 98 99
100
2 3 4 9 10 11 33 99 100
思路摘自https://www.cnblogs.com/zcr-blog/p/12634639.html
手工模拟如下
100
2 3 4 9 10 11 33 99 100
以上面数据作为说明
2<=k<=100
1.不是100的约数,那么是100-1=99的约数
k可取3,33,9,11,99
2.是100的约数,
备选数据有2,50,4,25,5,20,10,100
2:100/2=50,50/2=25,25%2=1选
50:100/50=2不选
4:100/4=25,25%4=1选
25:100/25=4不选
5:100/5=20,20/5=4不选
20:100/20=5不选
10:100/10=10,10/10=1选
100:100/100=1选
k可取2,4,10,100
综合两种情况,k可取3,33,9,11,99,2,4,10,100
1 不是 n的约数
这种情况比较简单,不是 n的约数根据题意 n 会一直减 k,减到 n<k。
最后得到的其实就是 n模k。
我们需要找的其实就是所有 k使得 n模k=1。
这其实就是 n−1的约数,所以直接查询 n−1 的约数(不包括1)个数即可。时间复杂度:O(√n)
k不是n的约数,是n-1的约数,证明如下:
n%k=1,即n=kx+1,x是整数,故n-1=kx,可得(n-1)%k=0,k是n-1的约数
2 是 n的约数
这种情况其实更好想。
我们首先要找到所有约数(不包括1),这样做的复杂度是O(√n)
根据题目要求我们要不断的除以这个约数,而因为 k≥2所以这是O(logn)的。
而当它不整除时,就变成了1,得到的会是 n模k(此时的 n 应是除以 k 若干遍后的 n),如果 n模k==1 则 ans++。
总复杂度 O(√nlog√n)。
记得 n一定是一个满足条件的 k。
记住要特判“2”。
这两种情况不存在相同的因子,因为相邻自然数互质。(摘自https://www.cnblogs.com/st1vdy/p/12634767.html)
AC代码如下
#include <stdio.h>
#define LL long long
LL n,cnt;
int judge(LL k,LL m){
while(m>=k){
if(m%k==0)m/=k;
else m%=k;
}
if(m==1)return 1;
else return 0;
}
int main(){
LL i;
scanf("%lld",&n);
if(n==2){printf("1\n");return 0;}//注意n=2需特判
for(i=2;i*i<=n-1;i++)//找n-1的约数
if((n-1)%i==0){
cnt++;
if(i!=(n-1)/i)cnt++;
}
cnt++;//加上n-1本身
for(i=2;i*i<=n;i++)
if(n%i==0){
if(judge(i,n))cnt++;
if(i!=n/i&&judge(n/i,n))cnt++;
}
cnt++;//加上n本身
printf("%lld\n",cnt);
}