Source:Ural SU Team.GOV Contest. Petrozavodsk Summer Session, August 2011
Online Judge:Ural 1851~1861
已经三场组队赛了,然后就是两天的休息调整~当然,还有总结!
今天做的题是区域赛难度的一套题,正如上面source所说的。今天我们队过了2题,成绩相当平凡,过的两题分别是1854题和1860题。在比赛过程中,我只起到一个助攻的作用...........
今天比赛前的运气不太好,在去院楼前突然觉得肚子痛了....囧,于是我就先解决拉肚子的问题再出发,所以....我又迟到了 - - 拉完肚子,状态不好也可以理解......去到机房,放下书包,队友就让我看看1860,一道递推公式的题。一开始队友解释题意错了,把计算质因数个数不假思索的看成直接求第n项。于是我就看了看题目数据,n<10^6,第一反应就是,水题??!怎么貌似没人做呢??我就跟队友讨论了一下,说道是否可以直接暴力得出结果。不过我喵了一下题目,马上发现队友坑我了....- - 原来这个是要求第n项的约数个数啊!然后我就顿时石化了......囧。于是我就想着,先放放吧.....
刚坐下不久就有人打算出1854,不过结果是wa。于是我想,有人敢动这题,就是说题目应该不会太难。所以,我就马上看这题了。记得昨天辛辛苦苦用Pollard_Rho做出了快速分解质因数的题,我一看懂题马上就想到这个算法了,结果今天用这个算法的时候又卡了.....- - 一个随机算法,我们为了排除随机的影响,不断的修改算法的参数,连续交了不下20次...结果都是返回tle或者wa,郁闷了足足两个钟。于是,我们又放一下这题,跑去尝试1861....刚开始;还以为1861是水题,于是就试着用暴力的方法贪心了个答案出来。当然,对于一道dp题,贪心不总是能取得最优解。当时我们就意识到这样的问题了,可是怎么找都找不到反例,也想不到怎么dp。这时,一个队友想到了1854的一个方法,他也跟我解释了他的想法,然后我也认同他的想法,就根据他的思路打了个代码。那个代码,本地测试小数据没有问题,所以我们就毫不犹豫的提交上去,AC了~
这时,有一个队伍过了递推公式的1860,所以我们也转向到投入到这题的解决上。我提供了一个方法,就是根据约数的求法,对数进行分解因子,然后把因子归类,统计得到因子数目。当时我们有想过,这可能是要用到欧拉等公式的数论题,不过我依然坚持着我的方法,不过就卡在如何统计因子个数这上面。不过我队友相当强大啊,瞬间就找到因子个数的规律了,可是要进行累加,应该会超时。然而,他很快又想到下一步,可以更快统计个数,不过思路还差一点。我听了他的想法后,嘿嘿~我的助攻出现了,告诉了他一个类似筛选素数的统计方法,然后很快就验证了可行性了。最后,我打出了代码,但是提交的时候出现了RE,不过也没事,我很快就排除了问题,是我设置错了一个变量,long long写成int了...- -!!提交上去就完美通过了~
其他题,很多看不懂,这是一个很严重的问题!还得继续加油啊!
组队,集思广益,几个人合作,说不定一道需要若干步骤的题就可以逐步排除疑问,最后得到满意的结果。1854,做这题的过程就很好说明了这个问题了!假设我们仍在个人赛的阶段,或许我们两个都不能做出这题了。另外一个,作为队友的队友,是一定要耐性听取队友的意见的。老实说,今天还真的差点就没认真听队友的想法,还差点就少出一题了 - - 以后要注意点,不然做少了题就不抵的!
刚开始组队,我就毛遂自荐,当了我们The_Judge的队长,我相信我一定能在和队友一同配合合作的前提下,带领团队走向胜利的~现在当务之急仍是要懂更多算法,提升自己综合能力!
下面是今天过的两道题的代码:
http://acm.timus.ru/problem.aspx?space=1&num=1854
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 7 #define debug 0 8 9 using namespace std; 10 11 typedef __int64 ll; 12 13 ll gcd(ll a, ll b){ 14 if (!b) return a; 15 return gcd(b, a % b); 16 } 17 18 ll multi(ll a, ll b, ll n){ 19 ll tmp = 0; 20 21 while (b){ 22 if (b & 1){ 23 tmp += a; 24 tmp %= n; 25 } 26 a <<= 1; 27 a %= n; 28 b >>= 1; 29 } 30 31 return tmp; 32 } 33 34 ll power(ll a, ll m, ll n){ 35 ll tmp = 1; 36 37 a %= n; 38 while (m){ 39 if (m & 1) tmp = multi(tmp, a, n); 40 a = multi(a, a, n); 41 m >>= 1; 42 } 43 44 return tmp; 45 } 46 47 bool mr(ll n){ 48 if (n == 2) return true; 49 if (n < 2 || ~n & 1) return false; 50 51 int t = 0; 52 ll a, x, y, u = n - 1; 53 54 while (~u & 1) t++, u >>= 1; 55 for (int i = 0; i < 8; i++){ 56 a = rand() % (n - 1) + 1; 57 x = power(a, u, n); 58 for (int j = 0; j < t; j++){ 59 y = multi(x, x, n); 60 if (y == 1 && x != 1 && x != n - 1) return false; 61 x = y; 62 } 63 if (x != 1) return false; 64 } 65 66 return true; 67 } 68 69 ll rho(ll n, ll c){ 70 ll x, y, d, i = 1, k = 2; 71 72 x = rand() % (n - 1) + 1; 73 y = x; 74 while (true){ 75 i++; 76 x = (multi(x, x, n) + c) % n; 77 d = gcd(y - x, n); 78 if (1 < d && d < n) return d; 79 if (x == y) return n; 80 if (i == k) y = x, k <<= 1; 81 } 82 } 83 84 void fac(ll n, int k, ll *p, int &cnt){ 85 if (n == 1) return ; 86 if (mr(n)){ 87 p[cnt++] = n; 88 return ; 89 } 90 91 ll t = n; 92 93 while (t >= n) t = rho(t, k--); 94 fac(t, k, p, cnt); 95 fac(n / t, k, p, cnt); 96 } 97 98 int main(){ 99 ll n; 100 int cnt; 101 ll f[80], ans; 102 bool cc; 103 104 while (~scanf("%I64d", &n)){ 105 cnt = 0; 106 fac(n, 107, f, cnt); 107 sort(f, f + cnt); 108 #if debug 109 for (int i = 0; i < cnt; i++){ 110 printf("%I64d\n", f[i]); 111 } 112 #endif 113 ans = 1; 114 f[cnt] = cc = 0; 115 for (int i = 0; i < cnt; i++){ 116 if (f[i] == f[i + 1]) ans *= f[i], cc = !cc; 117 else { 118 if (cc) { 119 ans *= f[i], 120 cc = false; 121 } 122 } 123 } 124 printf("%I64d\n", ans); 125 } 126 127 return 0; 128 }
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <iostream> 6 7 using namespace std; 8 typedef long long ll; 9 10 ll max2(ll a, ll b){ 11 return a > b ? a : b; 12 } 13 14 ll deal(ll n){ 15 ll ans = 1; 16 ll t1, t2, r; 17 18 for (ll i = 1, end = (ll)sqrt((double) n); i <= 1000005 && i < end; i++){ 19 if (n % i == 0){ 20 t1 = i * i; 21 t2 = n / i; 22 r = (ll) sqrt((double) i); 23 if (r * r == i){ 24 ans = max2(ans, i); 25 } 26 if (n % t1 == 0){ 27 ans = max2(ans, t1); 28 } 29 r = (ll) sqrt((double) t2); 30 if (r * r == t2){ 31 ans = t2; 32 break; 33 } 34 } 35 } 36 return ans; 37 } 38 39 40 int main(){ 41 ll n; 42 43 cin >> n; 44 cout << deal(n) << endl; 45 46 return 0; 47 }
两种代码的运行结果:
http://acm.timus.ru/problem.aspx?space=1&num=1860
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <iostream> 6 7 using namespace std; 8 typedef __int64 ll; 9 10 #define debug 0 11 12 const int maxn = 1000005; 13 const ll md = 1000000007; 14 15 ll fb[maxn + 10], pr[100000], pn, cntpr[100000], prcnt; 16 bool np[maxn + 10]; 17 18 void gf(){ 19 fb[0] = fb[1] = 1; 20 for (int i = 2; i < maxn; i++){ 21 fb[i] = fb[i - 1] + fb[i - 2]; 22 fb[i] %= md; 23 } 24 #if debug 25 for (int i = 0; i < 10; i++){ 26 printf("%lld ", fb[i]); 27 } 28 puts(""); 29 #endif 30 } 31 32 void gp(){ 33 memset(np, 0, sizeof(np)); 34 35 pn = 0; 36 np[0] = np[1] = true; 37 for (ll i = 2; i < maxn; i++){ 38 if (!np[i]){ 39 pr[pn++] = i; 40 } 41 for (ll j = 0; j < pn && pr[j] * i < maxn; j++){ 42 np[pr[j] * i] = true; 43 if (i % pr[j] == 0) break; 44 } 45 } 46 #if debug 47 printf("pn %lld\n", pn); 48 for (int i = 0; i < 10; i++){ 49 printf("%lld ", pr[i]); 50 } 51 puts(""); 52 #endif 53 } 54 55 ll deal(ll n){ 56 ll ep, i; 57 58 memset(cntpr, 0, sizeof(cntpr)); 59 for (i = 0; i < pn && pr[i] <= n; i++){ 60 #if debug 61 printf("%d %lld\n", i, pr[i]); 62 #endif 63 ep = pr[i]; 64 while (ep <= n){ 65 for (ll j = ep; j <= n; j += ep){ 66 cntpr[i] += fb[n - j]; 67 cntpr[i] %= md; 68 } 69 ep *= pr[i]; 70 } 71 } 72 #if debug 73 puts("pass"); 74 #endif 75 prcnt = i; 76 77 ll ans = 1; 78 79 for (i = 0; i < prcnt; i++){ 80 ans *= cntpr[i] + 1; 81 ans %= md; 82 } 83 84 return ans; 85 } 86 87 int main(){ 88 int n; 89 90 gp(); 91 gf(); 92 while (cin >> n) 93 cout << deal(n) << endl; 94 95 return 0; 96 }
——written by Lyon