码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #232 (Div. 1)

时间:2014-09-01 01:35:52      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   strong   ar   for   

这次运气比较好,做出两题。本来是冲着第3题可以cdq分治做的,却没想出来,明天再想好了。

A. On Number of Decompositions into Multipliers

题意:n个数a1,a2, a3...an求n个数相乘与a1*a2*a3*a4...an相等的排列个数。

分析:首先应该对ai分解质因数,求出所有ai中质因数及个数,枚举排列中每个数包含的质因数个数,例如质因数qi,有ni个,相应的排列中数包含质因数qi个数设为x1,x2,....xn, x1+x2+x3..+xn = ni , 那么对于qi共有C(ni+n-1, n-1)种情况。简单来说就是将ni分成n部分,这样想:有ni个球,需要分成n部分,也就是在n个球中插入n-1根木棍,这样分成n部分就相当于ni+n-1中选n-1个位置。最后把所有质因子可能的划分情况相乘起来就行了。

注意:分解质因数最后一个质因数可能很大!

代码:

bubuko.com,布布扣
 1 #include <bits/stdc++.h>
 2 #define in freopen("solve_in.txt", "r", stdin);
 3 #define bug(x) printf("Line %d : >>>>>>>\n", (x));
 4 #define pb push_back
 5 
 6 using namespace std;
 7 typedef long long LL;
 8 typedef map<int, int> Mps;
 9 const int M = (int)1e9+7;
10 const int maxn = 555;
11 const int maxm = (int)1e5 + 100;
12 LL inv[maxn];
13 int a[maxn];
14 Mps Div;
15 vector<int> dv;
16 
17 LL powmod(LL a, LL b) {
18     LL res = 1;
19     while(b) {
20         if(b&1)
21             res = (res*a)%M;
22         b >>= 1;
23         a = (a*a)%M;
24     }
25     return res;
26 }
27 void getInv(int n) {
28     for(int i = 1; i < n; i++) {
29         inv[i] = powmod(i, M-2);
30     }
31 }
32 void getDiv(int x) {
33     int m = (int)sqrt(x+.5);
34     for(int i = 2; i <= m; i++) {
35         if(x%i == 0) {
36             if(Div[i] == 0)
37                 dv.pb(i);
38             while(x%i == 0) {
39                 Div[i]++;
40                 x/=i;
41             }
42         }
43     }
44     if(x > 1) {
45         if(Div[x] == 0)
46             dv.pb(x);
47         Div[x]++;
48     }
49 }
50 LL nCr(LL n, LL m) {
51     LL res = 1;
52     for(int i = 0; i < m; i++) {
53         res = res*(n-i)%M*inv[i+1]%M;
54         if(res < 0)
55             res += M;
56     }
57     return (res + M)%M;
58 }
59 int main() {
60 
61     getInv(maxn);
62     int n;
63     scanf("%d", &n);
64     for(int i = 1; i <= n; i++) {
65         scanf("%d", a+i);
66         getDiv(a[i]);
67     }
68     LL ans = 1;
69     for(int i = 0; i < (int)dv.size(); i++) {
70         int x = dv[i];
71         ans = ans*nCr(Div[x]+n-1, n-1)%M;
72     }
73     cout<<ans<<endl;
74     return 0;
75 }
View Code

B. On Sum of Fractions

题意:给定n, u(i)表示不超过i的最大质数, v(i)表示大于i的最小质数。求对于所有的2<= i <= n , sum{1/(u(i)*v(i)}, 最简分式结果。

分析:

列出n的前几个数的1/u(i)*v(i),发现对于两个相邻素数pi, pi+1间的数i, 1/u(i)*v(i)结果是一样的。也就是说 对于  pi <= x   < pi+1, sum{1/u(x)v(x)},化简后就是, 1/u(x)-1/v(x), 得到这个结论后,每次找到大于n的一个素数pi+1,结果就变成两部分, x < pi, 和 pi <= x < n, 第一部分化简就是1/2-1/pi ,第二部分:n-pi+1/(pi*pi+1), 两者之和合并一下就会得到一个表达式:2*(n+1)-2*(pi+pi+1)-pi*pi+1/(2*pi*pi+1)。求质数,用Miller-Rabin法判断前后两个质数就可以了。

代码:

bubuko.com,布布扣
 1 #include <bits/stdc++.h>
 2 #define in freopen("solve_in.txt", "r", stdin);
 3 #define bug(x) printf("Line %d : >>>>>>>\n", (x));
 4 #define pb push_back
 5 
 6 using namespace std;
 7 typedef pair<int, int> PII;
 8 typedef long long LL;
 9 typedef map<int, int> Mps;
10 
11 LL powmod(LL a, LL b, LL c) {
12     LL res = 1;
13     while(b) {
14         if(b&1) res = res*a%c;
15         b >>= 1;
16         a = (a*a)%c;
17     }
18     return res;
19 }
20 bool test(int n, int a, int d) {
21     if(n == 2)return true;
22     if(n == a) return true;
23     if((n&1) == 0) return false;
24     while(!(d&1)) d >>= 1;
25     int t = powmod(a, d, n);
26     while((d != n-1) && (t != 1) && (t != n-1)) {
27         t = (LL)t*t%n;
28         d <<= 1;
29     }
30     return (t == n-1) || (d&1) == 1;
31 
32 }
33 bool isPrime(int n) {
34     if(n < 2) return false;
35     int a[] = {2, 3, 61};
36     for(int i = 0; i <= 2; i++) if(!test(n, a[i], n-1)) return false;
37     return true;
38 }
39 pair<LL, LL> getPrime(LL n) {
40     LL x = n;
41     x++;
42     PII ans;
43     while(1) {
44         if(isPrime(x)) {
45             ans.first = x;
46             break;
47         }
48         x++;
49     }
50     x = n;
51     while(1) {
52         if(isPrime(x)) {
53             ans.second = x;
54             break;
55         }
56         x--;
57     }
58     return ans;
59 }
60 LL getGcd(LL a, LL b) {
61     return !b ? a : getGcd(b, a%b);
62 }
63 int main() {
64 
65     int T;
66     int n;
67     for(int t = scanf("%d", &T); t <= T; t++) {
68         scanf("%d", &n);
69         if(n == 2) {
70             puts("1/6");
71         } else {
72             PII u = getPrime(n);
73             LL x = u.first, y = u.second;
74             LL a = 2*(n+1)-2*(x+y)+x*y;
75             LL b = 2*x*y;
76             LL c = getGcd(a, b);
77             printf("%I64d/%I64d\n", a/c, b/c);
78         }
79     }
80     return 0;
81 }
View Code

C. On Changing Tree

题意:

Codeforces Round #232 (Div. 1)

标签:style   blog   http   color   os   io   strong   ar   for   

原文地址:http://www.cnblogs.com/rootial/p/3948478.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!