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 }
View Code

事实上观察数据范围可以发现问题时间复杂度必然与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 }
View Code

高进制状压,当进制为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 }
View Code

考虑题目中的明显提示

posted @ 2021-08-07 21:37  HZOI_LYM  阅读(40)  评论(0编辑  收藏  举报