NOIP模拟32
T1:
暴力枚举判断最大质因数时间复杂度O(wsqrt(w))40pts
考虑原理模改线性筛素数时间复杂度O(w)60pts
发现问题在于冗余状态枚举,即筛素数过程中不严格沿
值域递增,于是set维护当前最小值进行线性筛,时间复杂度
O(klog(k))80pts
进一步发现事实上要保证筛素数过程中严格沿值域递增
并不需要维护全局最小值,我们只需要维护每种素数域下的
最小值选其进行线性筛即可,可以证明筛素数过程中严格沿
值域递增并且当前数的总数单调不降,时间复杂度O(k),100pts
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define I int 4 #define LL long long 5 I b,k,prime[16] = {0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47}; 6 queue <LL> q[16]; 7 signed main () { 8 scanf ("%d%d",&b,&k); 9 for (I i(1);i <= b; ++ i) q[i].push (prime[i]); 10 for (I i(1);i < k; ++ i) { 11 I pos; LL tmp (LONG_LONG_MAX); 12 for (I j(1);j <= b; ++ j) if (q[j].front () < tmp) 13 tmp = q[j].front (), pos = j; 14 q[pos].pop (); 15 if (i + 1 == k) { printf ("%lld\n",tmp); return 0; } 16 for (I j(1);j <= pos; ++ j) q[j].push (tmp * prime[j]); 17 } 18 }
事实上观察数据范围可以发现问题时间复杂度必然与k线性
相关考场时间复杂度计算错误导致80pts后停止优化
T2:
很容易想到唯一分解,发现条件二可以转化为对于任一
质因数其出现次数<=2且任一质因数组与其他质因数组并<=1
很容易发现可以进行状压DP,考虑记录质因子出现状态并枚
举满足条件的状态进行转移,由于合法状态数实际上并不多,
故时间复杂度1e6级
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define I int 4 #define LL long long 5 #define state1 (j & 1 << (k - 1)) 6 #define state2 (i >> 3 * (k - 1) & 7) 7 const I mod = 1e9 + 7; 8 signed main () { LL n,num[1 << 10]; I res,cnt,times[10],dp[300000]; 9 scanf ("%lld",&n); dp[0] = 1; 10 for (LL i(2);i * i <= n; ++ i) if (n % i == 0) { 11 cnt ++ ; while (n % i == 0) n /= i, times[cnt] ++ ; 12 } 13 if (n > 1) times[++cnt] = 1; 14 for (I i(1);i < 1 << cnt; ++ i) { 15 num[i] = 1; for (I j(1);j <= cnt; ++ j) if (i & 1 << j - 1) num[i] *= times[j]; 16 } 17 for (I i(0);i < 1 << cnt * 3; ++ i) if (dp[i]) { 18 res = (res + dp[i]) % mod; 19 for (I j(1);j < 1 << cnt; ++ j) { I pos(0), state(i), tmp(0); 20 for (I k(1);k <= cnt; ++ k) if (!state2 && state1) { pos = k; break; } 21 for (I k(1);k <= cnt; ++ k) if ( state2 && state1) 22 if (state2 == 7) goto flag; 23 else if (!tmp) tmp = state2; 24 else if (tmp != state2) goto flag; 25 for (I k(1);k <= cnt; ++ k) if (state1) 26 state |= state2 ? 7 << 3 * (k - 1) : pos << 3 * (k - 1); 27 dp[state] = (dp[state] + dp[i] * num[j]) % mod; flag : ; 28 } 29 }printf ("%d\n",res - 1); 30 }
高进制状压,当进制为2的指数时可以转化为二进制状压,根
据指数关系进行位数调整。
注意观察转化题目中关键信息。
T3:
发现一个很显然的提示为保证合法数严格不小于n/2,考
虑意义,随机条件下,任选两组数据计算出四个参数,由于
题目保证,故选对概率为1/4,选错为3/4,于是考虑多次选择
概率指数级上升,发现我们仅需要一组正确数据,故暴力高斯
消元进行check即可(注意acos函数需要人工调节正负),时间
复杂度O(n)
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define I int 4 #define B bool 5 #define V void 6 #define D double 7 const I N = 1e5 + 5; 8 const D eps = 1e-6; 9 I n; 10 struct POS{ D x1,y1,x2,y2; }pos[N]; 11 D A[10][10]; 12 inline V initital (I pos1,I pos2) { 13 A[1][1] = pos[pos1].x1, A[1][2] = -pos[pos1].y1, A[1][5] = pos[pos1].x2; 14 A[2][1] = pos[pos1].y1, A[2][2] = pos[pos1].x1, A[2][5] = pos[pos1].y2; 15 A[3][1] = pos[pos2].x1, A[3][2] = -pos[pos2].y1, A[3][5] = pos[pos2].x2; 16 A[4][1] = pos[pos2].y1, A[4][2] = pos[pos2].x1, A[4][5] = pos[pos2].y2; 17 A[1][3] = A[2][4] = A[3][3] = A[4][4] = 1; 18 } 19 inline V Gauss () { D rate; 20 for (I i(1),pos(i);i <= 4; ++ i,pos = i) { 21 for (I j(i + 1);j <= 4; ++ j) 22 if (fabs(A[j][i]) > fabs (A[pos][i])) 23 pos = j; 24 if (pos != i) swap (A[i],A[pos]); 25 for (I j(1);j <= 4; ++ j) if (j != i) { 26 rate = A[j][i] / A[i][i]; 27 for (I k(i);k <= 5; ++ k) A[j][k] -= A[i][k] * rate; 28 } 29 }for (I i(1);i <= 4; ++ i) A[i][5] /= A[i][i]; 30 } 31 inline D firx (I x,D s,D c,D d) { return pos[x].x1 * c - pos[x].y1 * s + d; } 32 inline D firy (I x,D s,D c,D d) { return pos[x].x1 * s + pos[x].y1 * c + d; } 33 inline B check () { 34 I sum (0); 35 D c(A[1][5]),s(A[2][5]),d1(A[3][5]),d2(A[4][5]); 36 for (I i(1);i <= n; ++ i) 37 if (fabs(firx (i,s,c,d1) - pos[i].x2) <= eps && fabs (firy (i,s,c,d2) - pos[i].y2) <= eps) sum ++ ; 38 return sum > n >> 1; 39 } 40 signed main () { 41 srand (time(0)); scanf ("%d",&n); 42 for (I i(1);i <= n; ++ i) scanf ("%lf%lf%lf%lf",&pos[i].x1,&pos[i].y1,&pos[i].x2,&pos[i].y2); 43 for (I i(1);i <= 50; ++ i) { 44 I x(rand () % n + 1), y(rand () % n + 1); 45 if (x == y) continue; 46 initital (x,y), Gauss (); 47 if (check ()) break; 48 } 49 D scale (sqrt (A[1][5] * A[1][5] + A[2][5] * A[2][5])); 50 A[1][5] /= scale; A[2][5] /= scale; A[1][5] = acos (A[1][5]) * (A[2][5] < 0 ? -1 : 1); 51 printf ("%.6lf\n%.6lf\n%.6lf %.6lf",A[1][5],scale,A[3][5],A[4][5]); 52 }
考虑题目中的明显提示