20170117小测

今天再次迎来了我们的例行考试。

T1:


首先我们考虑那些点是可以共存的,我们可以枚举一个质数做他们的gcd,然后把这些点放在一张图里求直径。
所以我们要做的就是把这些点的值分解质因数,对每个质因数挂一个链,代表有那些点包含这些质因数。然后我们枚举质因数,把这条链上的点放进图里求直径即可。由于质因数最多log个,所以复杂度nlogn。
然而分解质因数怎么做呢?10w个数,1e9的范围,暴力sqrt的分解肯定过不去,我们需要pollard rho。
然而考场上我想:pollard rho可能被卡(我才不告诉你我不会写pollard rho呢),暴力分解又过不去。况且暴力分解在最差情况下连5000都过不去,我还不如敲个n^2log的暴力呢,然后就敲了一个裸暴力进去。
结果正解就是sqrt的暴力分解,很多人都这样A了。也就是说,我们1e10的计算量信仰跑过了。行吧,我也没什么可说的了。
这道题目告诉我们即使再绝望也不要放弃骗分......
(感觉此题堪比以后要给高一考的4e8信仰背包,然而这次却并没有我那么良心的验题人)
考场15分代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define debug cout
 6 using namespace std;
 7 const int maxn=1e5+1e2;
 8 
 9 int in[maxn];
10 int s[maxn],t[maxn<<1],nxt[maxn<<1];
11 int val[maxn],dis[maxn];
12 int ans;
13 
14 inline int gcd(int a,int b) {
15     if( ! ( a && b ) ) return a | b;
16     register int t;
17     while( t = a % b )
18         a = b , b = t;
19     return b;
20 }
21 
22 inline void addedge(int from,int to) {
23     static int cnt = 0;
24     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
25 }
26 inline void dfs(int pos,int fa) {
27     ans = max( ans , dis[pos] );
28     for(int at=s[pos];at;at=nxt[at])
29         if( t[at] != fa ) {
30             int g = gcd(val[pos],in[t[at]]);
31             if( g != 1 ) {
32                 dis[t[at]] = dis[pos] + 1 , val[t[at]] = g;
33                 dfs(t[at],pos);
34             }
35         }
36 }
37 
38 int main() {
39     static int n;
40     scanf("%d",&n);
41     for(int i=1,a,b;i<n;i++) {
42         scanf("%d%d",&a,&b);
43         addedge(a,b) , addedge(b,a);
44     }
45     for(int i=1;i<=n;i++)
46         scanf("%d",in+i);
47     for(int i=1;i<=n;i++) {
48         val[i] = in[i] , dis[i] = 1;
49         dfs(i,-1);
50     }
51     
52     printf("%d\n",ans);
53     
54     return 0;
55 }
View Code


正解代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<map>
 7 #include<cmath>
 8 #define debug cout
 9 using namespace std;
10 const int maxn=1e5+1e2;
11 
12 map<int,int> mp;
13 vector<int> pts[maxn<<4];
14 int in[maxn];
15 int s[maxn],t[maxn<<1],nxt[maxn<<1];
16 bool can[maxn],vis[maxn];
17 int dis[maxn],root,mxp;
18 int n,m,ans,cnt;
19 
20 inline void addedge(int from,int to) {
21     static int cnt = 0;
22     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
23 }
24 inline void cut(int x,int p) {
25     int sq = sqrt(x);
26     for(int i=2;i<=sq&&i*i<=x;i++) {
27         if( ! ( x % i ) ) {
28             if( !mp.count(i) ) mp[i] = ++cnt;
29             pts[mp[i]].push_back(p);
30             while( ! ( x % i ) ) x /= i;
31         }
32     }
33     if( x != 1 ) {
34         if( !mp.count(x) ) mp[x] = ++cnt;
35         pts[mp[x]].push_back(p);
36     }
37 }
38 
39 inline void dfs(int pos,int fa) {
40     vis[pos] = 1;
41     if( dis[pos] > dis[mxp] ) mxp = pos;
42     for(int at=s[pos];at;at=nxt[at])
43         if( can[t[at]] && t[at] != fa ) {
44             dis[t[at]] = dis[pos] + 1;
45             dfs(t[at],pos);
46         }
47 }
48 inline void getans(int x) {
49     for(unsigned i=0;i<pts[x].size();i++)
50         can[pts[x][i]] = 1;
51     for(unsigned i=0;i<pts[x].size();i++)
52         if( !vis[pts[x][i]] ) {
53             mxp = 0;
54             dfs(pts[x][i],-1);
55             root = mxp , mxp = 0;
56             dis[root] = 1;
57             dfs(root,-1);
58             ans = max( ans , dis[mxp] );
59         }
60     for(unsigned i=0;i<pts[x].size();i++)
61         can[pts[x][i]] = vis[pts[x][i]] = dis[pts[x][i]] = 0;
62 }
63 
64 int main() {
65     scanf("%d",&n);
66     for(int i=1,a,b;i<n;i++) {
67         scanf("%d%d",&a,&b);
68         addedge(a,b) , addedge(b,a);
69     }
70     for(int i=1,x;i<=n;i++) {
71         scanf("%d",&x);
72         cut(x,i);
73     }
74     
75     for(int i=1;i<=cnt;i++)
76         getans(i);
77     
78     printf("%d\n",ans);
79     
80     return 0;
81 }
View Code

 

然后由于标程复杂度不对,我来补了一发Pollard rho。注意1w以下的数值暴力分解,否则根本跑不出来。还有为什么这玩意跑得比暴力还慢......

无视那个随机数种子什么的,这不重要。

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<map>
  6 #include<vector>
  7 #include<cstdlib>
  8 #define lli long long int
  9 #define bool unsigned char
 10 #define debug cout
 11 using namespace std;
 12 const int maxn=5e6+1e2;
 13 
 14 int in[maxn],dis[maxn],mxd,root;
 15 int s[maxn],t[maxn<<1],nxt[maxn<<1];
 16 bool can[maxn],vis[maxn];
 17 vector<int> pts[maxn];
 18 map<int,int> mp;
 19 int n,m,cnt,ans;
 20 
 21 namespace PollardRho {
 22     const int lst[15]={0,2,3,5,7,11,13,17,19,23,29,31,61,24251},lstlen=13;
 23     inline int fastpow(int base,int tme,int mod) {
 24         int ret = 1 , now = base;
 25         while( tme ) {
 26             if( tme & 1 ) ret = (lli) ret * now % mod;
 27             now = (lli) now * now % mod;
 28             tme >>= 1;
 29         }
 30         return ret % mod;
 31     }
 32     inline bool test(int x,int a) {
 33         int p = x - 1 , t = 0;
 34         while( ! ( p & 1 ) )
 35             p >>= 1 , ++t;
 36         p = fastpow(a,p,x);
 37         if( p == 1 || p == x - 1 ) return 1;
 38         while( t-- ) {
 39             p = (lli) p * p % x;
 40             if( p == x - 1 ) return 1;
 41         }
 42         return 0;
 43     }
 44     inline bool miller(int x) {
 45         for(int i=1;i<=lstlen;i++)
 46             if( x == lst[i] )return 1;
 47         for(int i=1;i<=lstlen;i++)
 48             if( ! ( x % lst[i]) ) return 0;
 49         for(int i=1;i<=lstlen;i++)
 50             if( !test(x,lst[i]) ) return 0;
 51         return 1;
 52     }
 53     inline int rnd(int x,int mod) {
 54         return ( (lli) x * x + 1 ) % mod;
 55     }
 56     inline int gcd(int a,int b) {
 57         if( ! ( a && b ) ) return a | b;
 58         register int t;
 59         while( t = a % b )
 60             a = b , b = t;
 61         return b;
 62     }
 63     inline void brute(int x,int p) {
 64         for(int i=2;i*i<=x;i++)
 65             if( ! ( x % i ) ) {
 66                 if( !mp.count(i) ) mp[i] = ++cnt;
 67                 pts[mp[i]].push_back(p);
 68                 while( ! ( x % i ) ) x /= i;
 69             }
 70         if( x != 1 ) {
 71             if( !mp.count(x) ) mp[x] = ++cnt;
 72             pts[mp[x]].push_back(p);
 73         }
 74     }
 75     inline void pollard(int x,int p) {
 76         if( x <= 10000 ) {
 77             brute(x,p);
 78             return;
 79         }
 80         if( miller(x) ) {
 81             if( !mp.count(x) ) mp[x] = ++cnt;
 82             pts[mp[x]].push_back(p);
 83             return;
 84         }
 85         int g , t1 = rnd(rand(),x) , t2 = rnd(t1,x);
 86         while( 1 ) {
 87             g = gcd( abs(t1-t2) , x );
 88             if( g != 1 && g != x ) break;
 89             t1 = rnd(t1,x) , t2 = rnd(t2,x) , t2 = rnd(t2,x);
 90             if( t1 == t2 ) {
 91                 //srand(time(0));
 92                 t1 = rand() % x + 1 , t2 = rand() % x + 1;
 93             }
 94         }
 95         pollard(g,p);
 96         pollard(x/g,p);
 97     }
 98 }
 99 using PollardRho::pollard;
100 
101 inline void addedge(int from,int to) {
102     static int cnt = 0;
103     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
104 }
105 inline void dfs(int pos,int fa) {
106     vis[pos] = 1;
107     if( dis[pos] > dis[mxd] ) mxd = pos;
108     for(int at=s[pos];at;at=nxt[at])
109         if( can[t[at]] && t[at] != fa ) {
110             dis[t[at]] = dis[pos] + 1;
111             dfs(t[at],pos);
112         }
113 }
114 inline void solve(const vector<int> &vec) {
115     for(unsigned i=0;i<vec.size();i++)
116         can[vec[i]] = 1;
117     for(unsigned i=0;i<vec.size();i++) {
118         if( vis[vec[i]] ) continue;
119         dis[vec[i]] = 1 , mxd = 0;
120         dfs(vec[i],-1);
121         dis[mxd] = 1;
122         dfs(mxd,-1);
123         ans = max( ans , dis[mxd] );
124     }
125     for(unsigned i=0;i<vec.size();i++)
126         dis[vec[i]] = vis[vec[i]] = can[vec[i]] = 0;
127 }
128 
129 int main() {
130     //srand(5201314);
131     srand(20010128^20010425);
132     scanf("%d",&n);
133     for(int i=1,a,b;i<n;i++) {
134         scanf("%d%d",&a,&b);
135         addedge(a,b) , addedge(b,a);
136     }
137     for(int i=1,x;i<=n;i++) {
138         scanf("%d",&x);
139         pollard(x,i);
140     }
141     
142     for(int i=1;i<=cnt;i++)
143         solve(pts[i]);
144     
145     printf("%d\n",ans);
146     
147     return 0;
148 }
View Code

 


T2:


首先呢,这是我完全没有思路的一道题......
正解是把树转化成DFS序,通过各种分类讨论把一对拼图和钥匙的作用范围转化为矩形,然后线段树+扫描线求矩形最大值......
具体题解请见SiriusRen的官方题解:

考场上我当然写了40分暴力啊,结果数据出锅没给暴力分(常数大的都跪了),我暴力爆零了啊......

考场爆零代码(本地测40):

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 const int maxn=2e3+1e2;
 8 const int inf=0x3f3f3f3f;
 9 
10 vector<int> pics[maxn],keys[maxn];
11 unsigned char vis[maxn];
12 int s[maxn],t[maxn<<1],nxt[maxn<<1],cnt;
13 int vals[maxn];
14 int ans;
15 
16 inline void addedge(int from,int to) {
17     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
18 }
19 
20 inline void dfs(int pos,int fa,int sum) {
21     for(unsigned i=0;i<keys[pos].size();i++)
22         vis[keys[pos][i]] = 1;
23     for(unsigned i=0;i<pics[pos].size();i++)
24         if( vis[pics[pos][i]] ) sum += vals[pics[pos][i]];
25     ans = max( ans , sum );
26     for(int at=s[pos];at;at=nxt[at])
27         if( t[at] != fa )
28             dfs(t[at],pos,sum);
29     for(unsigned i=0;i<keys[pos].size();i++)
30         vis[keys[pos][i]] = 0;
31 }
32 
33 inline void reset() {
34     memset(s,0,sizeof(s)) , cnt = 0;
35     for(int i=0;i<maxn;i++)
36         keys[i].clear() , pics[i].clear();
37     ans = -inf;
38 }
39 
40 int main() {
41     static int T,n,m;
42     scanf("%d",&T);
43     for(int t=1;t<=T;t++) {
44         reset();
45         scanf("%d%d",&n,&m);
46         for(int i=1,a,b;i<n;i++) {
47             scanf("%d%d",&a,&b);
48             addedge(a,b) , addedge(b,a);
49         }
50         for(int i=1,p,k;i<=m;i++) {
51             scanf("%d%d%d",&p,&k,vals+i);
52             pics[p].push_back(i) , keys[k].push_back(i);
53         }
54         for(int i=1;i<=n;i++)
55             dfs(i,-1,0);
56         printf("Case #%d: ",t);
57         printf("%d\n",ans);
58     }
59     
60     return 0;
61 }
View Code


正解代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define debug cout
  7 using namespace std;
  8 const int maxn=6e5+1e2;
  9 const int inf=0x3f3f3f3f;
 10 
 11 struct SegmentTree {
 12     int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3],lazy[maxn<<3],mx[maxn<<3],cnt;
 13     
 14     inline void build(int pos,int ll,int rr) {
 15         l[pos] = ll , r[pos] = rr;
 16         if( ll == rr ) return;
 17         const int mid = ( ll + rr ) >> 1;
 18         build(lson[pos]=++cnt,ll,mid);
 19         build(rson[pos]=++cnt,mid+1,rr);
 20     }
 21     inline void add(int pos,int x) {
 22         lazy[pos] += x , mx[pos] += x;
 23     }
 24     inline void push(int pos) {
 25         if( lazy[pos] ) {
 26             if( lson[pos] ) add(lson[pos],lazy[pos]);
 27             if( rson[pos] ) add(rson[pos],lazy[pos]);
 28             lazy[pos] = 0;
 29         }
 30     }
 31     inline void update(int pos,int ll,int rr,int x) {
 32         if( rr < l[pos] || r[pos] < ll ) return;
 33         if( ll <= l[pos] && r[pos] <= rr ) {
 34             add(pos,x);
 35             return;
 36         }
 37         push(pos);
 38         update(lson[pos],ll,rr,x);
 39         update(rson[pos],ll,rr,x);
 40         mx[pos] = max( mx[lson[pos]] , mx[rson[pos]] );
 41     }
 42     inline int query(int pos,int ll,int rr) {
 43         if( rr < l[pos] || r[pos] < ll ) return -inf;
 44         if( ll <= l[pos] && r[pos] <= rr ) return mx[pos];
 45         push(pos);
 46         return max( query(lson[pos],ll,rr) , query(rson[pos],ll,rr) );
 47     }
 48     inline void init() {
 49         memset(l+1,0,sizeof(int)*cnt) , memset(r+1,0,sizeof(int)*cnt),
 50         memset(lson+1,0,sizeof(int)*cnt) , memset(rson+1,0,sizeof(int)*cnt),
 51         memset(lazy+1,0,sizeof(int)*cnt) , memset(mx+1,0,sizeof(int)*cnt);
 52         cnt = 0;
 53     }
 54 }st;
 55 
 56 struct QNode {
 57     int x,sy,ty,delta;
 58     friend bool operator < (const QNode &a,const QNode &b) {
 59         return a.x != b.x ? a.x < b.x : a.delta < b.delta;
 60     }
 61 }ns[maxn<<3];
 62 int ncnt;
 63 
 64 
 65 int s[maxn],t[maxn<<1],nxt[maxn<<1],ecnt;
 66 int fa[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn];
 67 int dfn[maxn],mxd[maxn],dd;
 68 int sum[maxn],key[maxn],pic[maxn],val[maxn];
 69 int n,m,cntm;
 70 
 71 inline void addedge(int from,int to) {
 72     t[++ecnt] = to , nxt[ecnt] = s[from] , s[from] = ecnt;
 73 }
 74 inline void pre(int pos) {
 75     siz[pos] = 1;
 76     mxd[pos] = dfn[pos] = ++dd;
 77     for(int at=s[pos];at;at=nxt[at])
 78         if( t[at] != fa[pos] ) {
 79             dep[t[at]] = dep[pos] + 1 , fa[t[at]] = pos;
 80             pre(t[at]);
 81             mxd[pos] = mxd[t[at]];
 82             siz[pos] += siz[t[at]];
 83             son[pos] = siz[t[at]] > siz[son[pos]] ? t[at] : son[pos];
 84         }
 85 }
 86 inline void dfs(int pos) {
 87     top[pos] = pos == son[fa[pos]] ? top[fa[pos]] : pos;
 88     for(int at=s[pos];at;at=nxt[at])
 89         if( t[at] != fa[pos] )
 90             dfs(t[at]);
 91 }
 92 inline int lca(int a,int b) {
 93     while( top[a] != top[b] )
 94         if( dep[top[a]] > dep[top[b]] )
 95             a = fa[top[a]];
 96         else b = fa[top[b]];
 97     return dep[a] < dep[b] ? a : b;
 98 }
 99 inline int getd(int pos,int l) {
100     int last ;
101     while( top[pos] != top[l] )
102         last = top[pos] , pos = fa[top[pos]];
103     if( pos != l )
104         return son[l];
105     return last;
106 }
107 
108 inline void matrix_add(int sx,int tx,int sy,int ty,int delta) {
109     if( sx > tx || sy > ty ) return;
110     ns[++ncnt] = (QNode){sx,sy,ty,delta} ,
111     ns[++ncnt] = (QNode){tx+1,sy,ty,-delta};
112 }
113 
114 inline void reset() {
115     memset(s+1,0,sizeof(int)*ecnt) , memset(fa+1,0,sizeof(int)*n) ,
116     memset(dep+1,0,sizeof(int)*n) , memset(siz+1,0,sizeof(int)*n) ,
117     memset(son+1,0,sizeof(int)*n) , memset(top+1,0,sizeof(int)*n) ,
118     memset(dfn+1,0,sizeof(int)*dd) , memset(mxd+1,0,sizeof(int)*dd),
119     memset(sum+1,0,sizeof(int)*n)  , ncnt = cntm = n = m = dd = ecnt = 0;
120     st.init();
121 }
122 
123 inline int solve_node() {
124     int ret = -inf;
125     sort(ns+1,ns+ncnt+1);
126     st.build(st.cnt=1,1,dd);
127     for(int i=1;i<=ncnt;i++) {
128         if( ns[i].x != ns[i-1].x ) {
129             if(i-1) ret = max( ret , st.query(1,1,dd) );
130         }
131         st.update(1,ns[i].sy,ns[i].ty,ns[i].delta);
132     }
133     return ret;
134 }
135 
136 inline int build_matrix() {
137     int ret = 0;
138     for(int i=1;i<=cntm;i++) {
139         const int &a = key[i] , &b = pic[i];
140         int l = lca(a,b);
141         if( l != a && l != b ) {
142             matrix_add(dfn[a],mxd[a],dfn[b],mxd[b],val[i]);
143         } else {
144             if( l == a ) {
145                 int d = getd(b,a);
146                 matrix_add(1,dfn[d]-1,dfn[b],mxd[b],val[i]);
147                 matrix_add(mxd[d]+1,n,dfn[b],mxd[b],val[i]);
148             } else if( l == b ){
149                 int d = getd(a,b);
150                 matrix_add(dfn[a],mxd[a],1,dfn[d]-1,val[i]);
151                 matrix_add(dfn[a],mxd[a],mxd[d]+1,n,val[i]);
152             }
153         }
154     }
155     for(int i=1;i<=n;i++)
156         if( sum[i] ) {
157             ret += sum[i];
158             for(int at=s[i];at;at=nxt[at]) {
159                 const int tt = t[at];
160                 if( tt != fa[i] ) {
161                     matrix_add(dfn[tt],mxd[tt],dfn[tt],mxd[tt],-sum[i]);
162                 }
163             }
164             matrix_add(1,dfn[i]-1,1,dfn[i]-1,-sum[i]);
165             matrix_add(mxd[i]+1,n,mxd[i]+1,n,-sum[i]);
166             matrix_add(1,dfn[i]-1,mxd[i]+1,n,-sum[i]);
167             matrix_add(mxd[i]+1,n,1,dfn[i]-1,-sum[i]);
168         }
169     return ret;
170 }
171 inline int getans() {
172     pre(1) , dfs(1);
173     int preadd = build_matrix();
174     return preadd + solve_node();
175 }
176 
177 int main() {
178     static int T;
179     scanf("%d",&T);
180     for(int t=1;t<=T;t++) {
181         reset();
182         scanf("%d%d",&n,&m);
183         for(int i=1,a,b;i<n;i++) {
184             scanf("%d%d",&a,&b);
185             addedge(a,b) , addedge(b,a);
186         }
187         for(int i=1,a,b,v;i<=m;i++) {
188             scanf("%d%d%d",&a,&b,&v);
189             if( a == b ) sum[a] += v;
190             else pic[++cntm] = a , key[cntm] = b , val[cntm] = v;
191         }
192         printf("Case #%d: ",t);
193         printf("%d\n",getans());
194         
195     }
196     
197     return 0;
198 }
View Code

 


T3:

此题的重点是:题目的那个"的"字。
首先我们发现2k以内的质数只有300个,并且我们只用考虑奇偶就行。考虑用bitset维护每个数分解后的奇偶状态。
然后我就只会暴力了,手写了一个带<运算符的bitset丢到map里面暴力维护一下就好。
然后发现答案都是2^n-1,找了半天规律没找到,弃坑弃坑。
其实这个东西是线性基。我们考虑对每个质因数列一个方程,把每个数当做元。如果某个数是自由元的话,就证明这个数选和不选都有方案,所以我们可以枚举他选择还是不选。
于是我们对这个矩阵进行高斯消元,答案就是2^自由元个数-1。
当时yzy问我们他有没有讲过线性基,我们说没有,然后......

考场40分代码:

  1 #pragma GCC optimize(2)
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<bitset>
  7 #include<map>
  8 #define lli long long int
  9 #define debug cout
 10 using namespace std;
 11 const int maxn=3e2+1e1,maxm=2e3+1e2,lim=2e3;
 12 const int mod = 1e9+7;
 13 
 14 struct Pool {
 15     unsigned long long dat[5];
 16     const unsigned long long full = 0xffffffffffffffffull;
 17     
 18     inline int getbit(int pos) {
 19         int x = pos / 64 , y = pos % 64;
 20         return ( dat[x] >> y ) & 1;
 21     }
 22     inline void revbit(int pos) {
 23         int x = pos / 64 , y = pos % 64;
 24         dat[x] ^= ( 1ull << y );
 25     }
 26     friend Pool operator ^ (const Pool &a,const Pool &b) {
 27         Pool ret;
 28         for(int i=0;i<5;i++)
 29             ret.dat[i] = a.dat[i] ^ b.dat[i];
 30         return ret;
 31     }
 32     friend bool operator < (const Pool &a,const Pool &b) {
 33         for(int i=0;i<5;i++)
 34             if( a.dat[i] != b.dat[i] ) return a.dat[i] < b.dat[i];
 35         return 0;
 36     }
 37     inline void clear() {
 38         memset(dat,0,sizeof(dat));
 39     }
 40 }dv[maxn];
 41 
 42 map<Pool,int> mp[2];
 43 lli in[maxn],cpm[maxn];
 44 int prime[maxm],cnt;
 45 unsigned char vis[maxm];
 46 int n,cur;
 47 
 48 inline void sieve() {
 49     for(int i=2;i<=lim;i++) {
 50         if( !vis[i] ) prime[++cnt] = i;
 51         for(int j=1;j<=cnt&&i*prime[j]<=lim;j++) {
 52             vis[i*prime[j]] = 1;
 53             if( !( i % prime[j] ) ) break;
 54         }
 55     }
 56 }
 57 
 58 inline void cut(int p,lli x) {
 59     for(int i=1;i<=cnt;i++)
 60         while( ! ( x % prime[i] ) ) {
 61             dv[p].revbit(i) , x /= prime[i];
 62         }
 63 }
 64 
 65 inline void getans() {
 66     cur = 0;
 67     mp[cur][dv[0]] = 0;
 68     for(int i=1;i<=n;i++) {
 69         mp[cur^1] = mp[cur];
 70         for(map<Pool,int>::iterator it=mp[cur].begin();it!=mp[cur].end();++it) {
 71             Pool tar = it->first ^ dv[i];
 72             mp[cur^1][tar] += it->second , mp[cur^1][tar] %= mod;
 73         }
 74         mp[cur^1][dv[i]]++ , mp[cur^1][dv[i]] %= mod;
 75         cur ^= 1;
 76     }
 77 }
 78 
 79 inline void clear() {
 80     mp[0].clear() , mp[1].clear();
 81     for(int i=0;i<maxn;i++) dv[i].clear();
 82     memset(cpm,0,sizeof(cpm));
 83 }
 84 
 85 
 86 int main() {
 87     sieve();
 88     static int T;
 89     scanf("%d",&T);
 90     for(int t=1;t<=T;t++) {
 91         clear();
 92         scanf("%d",&n);
 93         if( n <= 20 ) {
 94             for(int i=1;i<=n;i++) {
 95                 lli x;
 96                 scanf("%lld",&x);
 97                 cut(i,x);
 98             }
 99             getans();
100             printf("Case #%d:\n",t);
101             printf("%d\n",mp[cur][dv[0]]);
102         }
103         
104     }
105     return 0;
106 }
View Code


正解代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<bitset>
 6 #define lli long long int
 7 using namespace std;
 8 const int maxn=3e2+1e1,lim=2e3;
 9 const int mod=1e9+7;
10 
11 int prime[maxn],cnt;
12 bitset<maxn> bs[maxn];
13 int n;
14 
15 inline void sieve() {
16     static unsigned char vis[lim+10];
17     for(int i=2;i<=lim;i++) {
18         if( !vis[i] ) prime[++cnt] = i;
19         for(int j=1;j<=cnt&&i*prime[j]<=lim;j++) {
20             vis[i*prime[j]] = 1;
21             if( ! ( i % prime[j] ) ) break;
22         }
23     }
24 }
25 
26 inline lli fastpow(lli base,int tme,int mod) {
27     lli ret = 1;
28     while( tme ) {
29         if( tme & 1 ) ret = ret * base % mod;
30         base = base * base % mod;
31         tme >>= 1;
32     }
33     ret = ( ( ret - 1 ) % mod + mod ) % mod;
34     return ret;
35 }
36 
37 inline int gauss() {
38     int ret = 0 , used = 0;
39     for(int i=1;i<=n;i++) {
40         int pos = -1;
41         for(int j=used+1;j<=cnt;j++)
42             if( bs[j][i] ) {
43                 pos = j;
44                 break;
45             }
46         if( !~pos ) {
47             ++ret;
48             continue;
49         }
50         swap(bs[pos],bs[++used]);
51         for(int j=1;j<=cnt;j++)
52             if( j != used && bs[j][i] )
53                 bs[j] ^= bs[used];
54     }
55     return ret;
56 }
57 
58 inline void cut(int p,lli x) {
59     for(int i=1;i<=cnt;i++)
60         while( ! ( x % prime[i] ) )
61             bs[i][p] = !bs[i][p] ,
62             x /= prime[i];
63 }
64 
65 inline void init() {
66     for(int i=0;i<maxn;i++)
67         bs[i] &= 0;
68 }
69 
70 int main() {
71     static int T;
72     sieve();
73     scanf("%d",&T);
74     for(int t=1;t<=T;t++) {
75         init();
76         scanf("%d",&n);
77         for(int i=1;i<=n;i++) {
78             lli x;
79             scanf("%lld",&x);
80             cut(i,x);
81         }
82         printf("Case #%d:\n",t);
83         printf("%lld\n",fastpow(2,gauss(),mod));
84     }
85     return 0;
86 }
View Code

 


本次考试并不是题的问题,主要还是我太菜。T1完全可以特判范围采用那种暴力,即使不能AC也能多骗点分吧,T3如果仔细想想也是可以做出来的,T2的暴力,如果没有用vector而是选择挂链,少打几个头文件的话估计也是能有分的(卡常这个事可能谁也救不了我了)。(T2正解DFS序转矩阵+分类讨论脑洞太大想不出来算了)

最后附上rank榜,这次题目变成这样也是没谁了。

posted @ 2018-01-17 22:44  Cmd2001  阅读(363)  评论(0编辑  收藏  举报