2017 多校联合训练 5 题解

Problem 1001

先预处理出一个数组,记录每个数对(x,y),y是x的倍数

用一个bitset A把a数组记录下来

然后用一个数组统计b数组

再用s数组维护一个后缀,s[x]表示大于x所有出现的数的个数的奇偶性

然后对于每一个未出现过的询问k,每个b数组中有的大于k的数,用bitset B记录它的倍数出现数的奇偶性

最后答案为(A>>k)&B中1的奇偶行与s[k+1]的异或值

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<string>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #include<queue>
12 #include<bitset>
13 using namespace std;
14 const int inf=(1<<30)-1;
15 const int maxn=50010;
16 #define REP(i,n) for(int i=(0);i<(n);i++)
17 #define FOR(i,j,n) for(int i=(j);i<=(n);i++)
18 typedef long long ll;
19 typedef pair<int,int> PII;
20 int IN(){
21     int c,f,x;
22     while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
23     while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
24 }
25 #define MP make_pair
26 #define fi first
27 #define se second
28 int n,m,q;
29 int a[maxn],b[maxn],tot,k,ans[maxn];
30 bitset<maxn> A,B,tmp;
31 
32 PII cnt[maxn*20];
33 PII t[maxn];
34 
35 void init()
36 {
37     tot=0;
38     for(int i=maxn-5;i>=1;i--)
39         for(int j=i;j<=maxn-5;j+=i)
40             cnt[++tot]=MP(i,j);
41 }
42 bool cmp(const PII &x,const PII & y) {return x.fi>y.fi;}
43 bool vis[maxn],s[maxn];
44 int main(){
45     init();
46     int T;scanf("%d",&T);
47     while(T--)
48     {
49         A.reset();
50         B.reset();
51         memset(vis,0,sizeof(vis));
52         memset(s,0,sizeof(s));
53         n=IN();m=IN();q=IN();
54         for(int i=1;i<=n;i++)
55             a[i]=IN(),A[a[i]]=1;
56         for(int i=1;i<=m;i++)
57             b[i]=IN(),vis[b[i]]=1;
58         for(int i=50000;i>=0;i--)
59             s[i]=vis[i+1]^s[i+1];
60         for(int i=1;i<=q;i++)
61             t[i].fi=IN(),t[i].se=i;
62         sort(t+1,t+q+1,cmp);
63         int p=1;
64         for(int i=1;i<=q;i++)
65         {
66             int k=t[i].fi;
67             if(i>1&&k==t[i-1].fi) {
68                 ans[t[i].se]=ans[t[i-1].se];
69                 continue;
70             }
71             for(;p<=tot&&cnt[p].fi>k;p++)
72                 if(vis[cnt[p].fi])
73                 {
74                     B[cnt[p].se]=B[cnt[p].se]^1;
75                     //cout<<vis[cnt[p]].se<<" "<<vis[cnt[p]].fi<<endl;
76                 }
77             tmp=A>>k;
78             tmp&=B;
79             ans[t[i].se]=(tmp.count()&1);
80             if(A[k]) ans[t[i].se]^=s[k];
81         }
82         for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
83     }
84     return 0;
85 }
View Code

 

Problem 1002

如果没有反字符串的限制,那么是一道经典的AC自动机

预处理所有正串和反串的AC自动机
从中间向两边dp

然后暴力枚举从中间向左右的字符

统计哪些串已经出现过

这时可以暴力枚举dp的初始值

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cstring>
  7 #include<string>
  8 #include<vector>
  9 #include<map>
 10 #include<set>
 11 #include<queue>
 12 using namespace std;
 13 struct node
 14 {
 15     int next[2];
 16     int fail,flag;
 17     /*void init()
 18     {
 19         memset(next,0,sizeof(next));
 20         fail=0;
 21         flag=0;
 22     }*/
 23 } trie[200],T[200];
 24 int tot;
 25 void init()
 26 {
 27     tot=0;
 28     memset(trie,0,sizeof(trie));
 29 }
 30 void insert(char *str,int val)
 31 {
 32     int p=0,index,i,l=strlen(str);
 33     for (i=0;i<l;i++)
 34     {
 35         index=str[i]-'0';
 36         if (trie[p].next[index]==0)
 37         {
 38             trie[p].next[index]=++tot;
 39             //cout<<"hhhhhhh"<<endl;
 40         }
 41         p=trie[p].next[index];
 42     }
 43     trie[p].flag|=(1<<val);
 44 }
 45 int go[2][200][2],w[2][200];
 46 void build_fail(int pd)
 47 {
 48     queue<int> Q;
 49     /*int i;
 50     for (i=0;i<2;i++)
 51         if (trie[0].next[i])
 52             Q.push(trie[0].next[i]);
 53     while (!Q.empty())
 54     {
 55         int k=Q.front();
 56         trie[k].flag|=trie[trie[k].fail].flag;
 57         for (i=0;i<2;i++)
 58         {
 59             int j=trie[k].next[i];
 60             if (j==0) trie[k].next[i]=trie[trie[k].fail].next[i];
 61             else
 62             {
 63                 trie[j].flag|=trie[k].flag;
 64                 trie[j].fail=trie[trie[k].fail].next[i];
 65                 Q.push(j);
 66             }
 67         }
 68         Q.pop();
 69     }*/
 70     int p,son,cur,i;
 71     Q.push(0);
 72     while (!Q.empty())
 73     {
 74         p=Q.front();
 75         Q.pop();
 76         for (i=0;i<2;i++)
 77         {
 78             if (trie[p].next[i]!=0)
 79             {
 80                 son=trie[p].next[i];
 81                 cur=trie[p].fail;
 82                 if (p==0)
 83                     trie[son].fail=0;
 84                 else
 85                 {
 86                     while (cur&&trie[cur].next[i]==0)
 87                         cur=trie[cur].fail;
 88                     trie[son].fail=trie[cur].next[i];
 89                 }
 90                 trie[son].flag=trie[son].flag|trie[trie[son].fail].flag;
 91                 Q.push(son);
 92             }
 93             else
 94             {
 95                 trie[p].next[i]=trie[trie[p].fail].next[i];
 96             }
 97         }
 98     }
 99     for (i=0;i<=tot;i++)
100     {
101         go[pd][i][0]=trie[i].next[0];
102         go[pd][i][1]=trie[i].next[1];
103         w[pd][i]=trie[i].flag;
104     }
105     if (pd==0) memcpy(T,trie,sizeof(trie));
106 }
107 const int mo=998244353;
108 int _,n,L;
109 char s[11][31];
110 int dp[2][70][130][130];
111 void upd(int &x,int y)
112 {
113     x=(x+y)%mo;
114 }
115 int main()
116 {
117     scanf("%d",&_);
118     while (_--)
119     {
120         init();
121         scanf("%d%d",&n,&L);
122         int i,j,k1,k2,k,len1,len2;
123         for (i=1;i<=n;i++)
124         {
125             scanf("%s",s[i]);
126             insert(s[i],i-1);
127         }
128         build_fail(0);
129         len1=tot;
130         init();
131         for (i=1;i<=n;i++)
132         {
133             int l=strlen(s[i]);
134             for (j=0;j<l;j++)
135                 if (l-j-1>j) swap(s[i][j],s[i][l-j-1]);
136         }
137         for (i=1;i<=n;i++)
138             insert(s[i],i-1);
139         build_fail(1);
140         len2=tot;
141         for (i=1;i<=n;i++)
142         {
143             int l=strlen(s[i]);
144             for (j=0;j<l;j++)
145                 if (l-j-1>j) swap(s[i][j],s[i][l-j-1]);
146         }
147         memset(dp,0,sizeof(dp));
148         int l=0;
149         for (i=1;i<=n;i++)
150             l=max(l,(int)strlen(s[i]));
151         l=min(l,L);
152         for (int W=0;W<(1<<l);W++)
153         {
154             int now=0,pd=0;
155             for (i=0;i<l;i++)
156             {
157                 int k=((W&(1<<i))>0);
158                 now=trie[now].next[k];
159                 pd|=trie[now].flag;
160             }
161             for (i=l-1;i>=0;i--)
162             {
163                 int k=((W&(1<<i))==0);
164                 now=trie[now].next[k];
165                 pd|=trie[now].flag;
166             }
167             int k1=now;
168             now=0;
169             for (i=l-1;i>=0;i--)
170             {
171                 int k=((W&(1<<i))>0);
172                 now=T[now].next[k];
173             }
174             dp[0][pd][now][k1]++;
175             //cout<<0<<" "<<pd<<" "<<now<<" "<<k1<<endl;
176         }
177         int now=0;
178         for (i=l+1;i<=L;i++)
179         {
180             int nex=now^1;
181             int W=0;
182             memset(dp[nex],0,sizeof(dp[nex]));
183             for (j=0;j<(1<<n);j++)
184                 for (k1=0;k1<=len1;k1++)
185                     for (k2=0;k2<=len2;k2++)
186                         if (W=dp[now][j][k1][k2])
187                             for (k=0;k<2;k++)
188                             {
189                                 int k3=T[k1].next[k],k4=trie[k2].next[k^1];
190                                 upd(dp[nex][j|T[k3].flag|trie[k4].flag][k3][k4],W);
191                             }
192             now=nex;
193         }
194         int ans=0;
195         for (i=0;i<=len1;i++)
196             for (j=0;j<=len2;j++)
197                 upd(ans,dp[now][(1<<n)-1][i][j]);
198         printf("%d\n",ans);
199     }
200     return 0;
201 }
View Code

Problem 1006

m<n时连成一个菊花图

m>=n时,剩下的每一条边将每一对点的距离缩减为1

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
 6 #define dec(i, a, b)    for (int i(a); i >= (b); --i)
 7 
 8 typedef long long LL;
 9 int T;
10 LL n, m;
11 LL ans;
12 
13 int main(){
14 
15 
16     scanf("%d", &T);
17     while (T--){
18         scanf("%lld%lld", &n, &m);
19         LL ans = n*n*n - n*n;
20 
21         LL dx = (n - 1) * 2;
22         LL dy = dx - 2;
23 
24         if (m >= n){
25             LL op = m;
26             rep(i, 1, n - 1){
27                 ans -= dx;
28                 dx += dy;
29             }
30 
31             LL yy = m - (n - 1);
32             ans -= yy * 2;
33 
34             ans = max(ans, n * (n - 1));
35             printf("%lld\n", ans);
36             
37 
38         }
39 
40         else{
41             rep(i, 1, m){
42                 ans -= dx;
43                 dx += dy;
44             }
45 
46             ans = max(ans, n * (n - 1));
47 
48             printf("%lld\n", ans);
49         }
View Code

 

Problem 1008

从前往后枚举

把缺的数补完整即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<string>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #include<queue>
12 using namespace std;
13 typedef long long ll;
14 int _,n,m;
15 ll b[10010],now[10010],a[10010],as[10010],p[10010];
16 ll C[61][61];
17 void init()
18 {
19     int i,j;
20     for (i=0;i<=50;i++)
21     {
22         C[i][0]=1;
23         C[i][i]=1;
24     }
25     for (i=1;i<=50;i++)
26         for (j=1;j<=50;j++)
27             C[i][j]=C[i-1][j]+C[i-1][j-1];            
28 }
29 int main()
30 {
31     init();
32     scanf("%d",&_);
33     while (_--)
34     {
35         scanf("%d%d",&n,&m);
36         int i,j,k;
37         for (i=0;i<=m;i++)
38             scanf("%lld",&b[i]);
39         memset(now,0,sizeof(now));
40         memset(a,0,sizeof(a));
41         memset(p,0,sizeof(p));
42         int t=0,tt=0;
43         //cout<<b[0]<<" "<<now[1]<<endl;
44         now[0]=1;
45         for (i=1;i<=m;i++)
46         {
47             //cout<<i<<" "<<b[i]<<" "<<now[i]<<endl;
48             if (now[i]<b[i])
49             {
50                 a[i]=b[i]-now[i];
51                 //cout<<i<<" "<<now[6]<<endl;
52                 tt+=a[i];
53                 if (tt==n) break;        
54                 int mx=0;
55                 //if (t>m) break;
56                 //if (a[i]>50) break;
57                 //cout<<i<<" "<<t<<endl;
58                 memset(p,0,sizeof(p));
59                 for (j=1;j<=a[i];j++)
60                 {
61                     for (k=0;k<=t;k++)
62                     {
63                         ll x=0;
64                         if (k+i*j>m) break;
65                         p[k+i*j]+=now[k]*C[a[i]][j],mx=max(mx,k+i*j);
66                         //if (k+i*j==6) cout<<i<<" "<<a[i]<<" "<<k<<" "<<now[k]<<" "<<C[a[i]][j]<<endl;
67                         //cout<<k<<" "<<i<<" "<<j<<" "<<k+i*j<<" "<<now[k+i*j]<<endl;
68                     }
69                 }
70                 t=mx;
71                 for (j=0;j<=t;j++)
72                 now[j]+=p[j];        
73             }
74         }
75         int tot=0;
76         for (i=1;i<=m;i++)
77             for (j=1;j<=a[i];j++)
78                 as[++tot]=i;
79         for (i=1;i<tot;i++)
80             printf("%lld ",as[i]);
81         printf("%lld\n",as[tot]);
82     }
83     return 0;
84 }
View Code

Problem 1011

排序后从最后一个数开始扫

只要判断有多少对相邻的数的差<=k即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=(1<<30)-1;
 4 const int maxn=100010;
 5 #define REP(i,n) for(int i=(0);i<(n);i++)
 6 #define FOR(i,j,n) for(int i=(j);i<=(n);i++)
 7 typedef long long ll;
 8 int n,k;
 9 int T;
10 int a[maxn];
11 int main()
12 {
13     scanf("%d",&T);
14     while(T--)
15     {
16         scanf("%d%d",&n,&k);
17         for(int i=1;i<=n;i++)
18         scanf("%d",&a[i]);
19         sort(a+1,a+n+1);
20         int ans=1;
21         for(int i=n;i>=2;i--)
22         if(abs(a[i]-a[i-1])<=k) ans++;
23         else break;
24         printf("%d\n",ans);
25     }
26     return 0;
27 }
View Code

 

posted @ 2017-08-27 22:46  cxhscst2  阅读(151)  评论(0编辑  收藏  举报