7-6 连续因子
1.题意
给定任一正整数n,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列(因子不包括1)。
2.题解
枚举除1之外的n的因子,最大枚举到对n开方+1即可。对每个枚举的因子判断它的连续因子的长度,并记录第一个因子,用于输出,最终输出维护的长度及序列。
3.代码
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn = 2e5 + 5; 5 const int INF = 1e9 + 5; 6 ll n, temp; 7 int main() { 8 cin >> n; 9 int first = 0; 10 int len = 0; 11 int mmax = sqrt(n)+1; 12 for(int i = 2; i <= mmax; i++) { 13 int j; 14 temp = 1; 15 for(j = i; j <= mmax; j++) { 16 temp *= j; 17 if(n % temp != 0) { 18 break; 19 } 20 } 21 if(j - i > len) { 22 len = j - i; 23 first = i; 24 } 25 } 26 if(first == 0) { 27 cout << 1 << endl << n; 28 } else{ 29 cout << len << endl << first; 30 for(int i = 1; i < len; i++) { 31 cout << '*' << first + i; 32 } 33 cout << endl; 34 } 35 36 return 0; 37 }
7-9 特立独行的幸福
1.题意
对一个十进制数的各位数字做一次平方和,称作一次迭代。如果一个十进制数能通过若干次迭代得到 1,就称该数为幸福数。显然,在一个幸福数迭代到 1 的过程中经过的数字都是幸福数,它们的幸福是依附于初始数字的。而一个特立独行的幸福数,是在一个有限的区间内不依附于任何其它数字的;其独立性就是依附于它的的幸福数的个数。如果这个数还是个素数,则其独立性加倍。列出给定区间内的所有特立独行的幸福数和它的独立性,如果区间内没有幸福数,则在一行中输出 SAD。
2.题解
把区间的数遍历一遍,判断它是否为特立独行幸福数,并将过程中产生的幸福数和非幸福数进行标记,用vector数组存每个特立独行的幸福数的附属幸福数,最后再判断一下是否是素数。
3.代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e4 + 5; 4 int vis0[maxn]; 5 int vis1[maxn]; 6 int vis[maxn]; 7 vector<int> v[maxn]; 8 bool prime(int n) { 9 if(n <= 1) { 10 return false; 11 } 12 for(int i = 2; i * i <= n; i++) { 13 if(n % i == 0) { 14 return false; 15 } 16 } 17 return true; 18 } 19 int pfh(int n) { 20 int ans = 0; 21 while(n) { 22 int tmp = n % 10; 23 ans += tmp * tmp; 24 n /= 10; 25 } 26 return ans; 27 } 28 bool judge(int n) { 29 vis[n] = 1; 30 int ux = n; 31 while(1) { 32 ux = pfh(ux); 33 if(ux == 1) { 34 return true; 35 } 36 if(vis[ux]) { 37 return false; 38 } 39 vis[ux] = 1; 40 v[n].push_back(ux); 41 } 42 } 43 int main() { 44 int l, r; 45 cin >> l >> r; 46 for(int i = l; i <= r; i++) { 47 if(!vis0[i] && !vis1[i]) { 48 memset(vis, 0, sizeof(vis)); 49 if(judge(i)) { 50 vis1[i] = 1; 51 for(int j = 0; j < v[i].size(); j++) { 52 vis1[v[i][j]] = 1; 53 } 54 } else { 55 vis0[i] = 1; 56 for(int j = 0; j < v[i].size(); j++) { 57 vis0[i] = 1; 58 } 59 } 60 } 61 } 62 for(int i = l; i <= r; i++) { 63 for(int j = 0; j < v[i].size(); j++) { 64 vis1[v[i][j]] = 0; 65 } 66 } 67 int flag=0; 68 for(int i = l; i <= r; i++) { 69 if(vis1[i]) { 70 flag = 1; 71 int ans = v[i].size() + 1; 72 if(prime(i)) { 73 ans *= 2; 74 } 75 cout << i << " " << ans << endl; 76 } 77 } 78 if(!flag) { 79 cout << "SAD" << endl; 80 } 81 82 return 0; 83 }
7-12 功夫传人
1.题意
某一位祖师爷门下的徒子徒孙家谱:假设家谱中的每个人只有1位师傅(除了祖师爷没有师傅);每位师傅可以带很多徒弟;并且假设辈分严格有序,即祖师爷这门武功的每个第i代传人只能在第i-1代传人中拜1个师傅。我们假设已知祖师爷的功力值为Z,每向下传承一代,就会减弱r%,除非某一代弟子得道(功力放大给定倍数)。现给出师门谱系关系,要求你算出所有得道者的功力总值。输入在第一行给出3个正整数,分别是:N——整个师门的总人数(每个人从0到N−1编号,祖师爷的编号为0);Z——祖师爷的功力值;r ——每传一代功夫所打的折扣百分比值。接下来有N行,第i行(i=0,⋯,N−1)描述编号为i的人所传的徒弟,第一个数字是徒弟的个数,后面跟的是各位徒弟的编号,数字间以空格间隔。第一个数字为零表示这是一位得道者,这时后面跟的一个数字表示其武功被放大的倍数。
2.题解
把每位师傅的徒弟用vector数组存下来,用一个单独的数组存得道者的数据,dfs搜索,如果是得道者就累加功力,否则接着搜。
3.代码
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 vector<int> child[100005]; 5 double z, r, sum; 6 double val[100005]; 7 void dfs(int id, double w) { 8 if(val[id]) { 9 sum += w * val[id]; 10 } else { 11 for(int i = 0; i < child[id].size(); i++) { 12 dfs(child[id][i], w * r); 13 } 14 } 15 return; 16 } 17 int main() { 18 //memset(val, 0, sizeof(val)); 19 //sum=0; 20 int n, m, v; 21 scanf("%d %lf %lf", &n, &z, &r); 22 r = (100 - r) / 100; 23 for(int i = 0; i < n; i++) { 24 scanf("%d", &m); 25 if(m == 0) { //将所有突变的倍数储存在数组里 26 scanf("%lf", &val[i]); 27 } else { 28 for(int j = 0; j < m; j++) { 29 scanf("%d", &v); 30 child[i].push_back(v); 31 } 32 } 33 } 34 dfs(0, z); 35 printf("%d ", (int)sum); 36 37 return 0; 38 }