2019牛客多校第五场
A.digits 2
传送:https://ac.nowcoder.com/acm/contest/885/A
题意:构造一个不超过$10^4$位的十进制数,且满足这个数是$n$的倍数,且每一位的和是$n$的倍数。
数据范围:$1<=n<=100$。
分析:直接构造$n$个$n$即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main(){ 4 int t,x;scanf("%d",&t); 5 while (t--){ 6 scanf("%d",&x); 7 for (int i=0;i<x;i++) printf("%d",x); 8 printf("\n"); 9 } 10 return 0; 11 12 }
B.generator 1
传送:https://ac.nowcoder.com/acm/contest/885/B
题意:已知$x_0,x_1,a,b$,且$x_i=a*x{i-1}+b*x_{i-2}$。求解$x_n%mod$。
数据范围:$1<=x_0,x_1,a,b<=10^9,1<=n<=10^{10^6},1<=mod<=2 \times 10^9$。
分析:开始考虑矩阵快速幂。但$n$范围过大,开始考虑把高精度$n$分解为二进制数,然后做矩阵快速幂。
但是进制转换会tle。正解是十进制快速幂+矩阵快速幂。
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 typedef long long ll; 5 const int N=1e6+10; 6 struct mat{ll a[2][2];}; 7 ll x0,x1,a,b,mod; char n[N]; 8 mat mat_mul(mat x,mat y){ 9 mat ans; 10 memset(ans.a,0,sizeof(ans.a)); 11 for (int i=0;i<2;i++){ 12 for (int j=0;j<2;j++) 13 for (int k=0;k<2;k++) 14 (ans.a[i][j]+=(x.a[i][k]*y.a[k][j])%mod)%=mod; 15 } 16 return ans; 17 } 18 ll mat_pow(){ 19 mat c,res; 20 c.a[0][0]=a;c.a[0][1]=b;c.a[1][0]=1;c.a[1][1]=0; 21 res.a[0][0]=x1; res.a[1][0]=x0; res.a[0][1]=res.a[1][1]=0; 22 int len=strlen(n); 23 for (int i=len-1;i>=0;i--){ 24 int kk=n[i]-'0'; mat tmp=c; 25 for (int j=0;j<kk;j++) res=mat_mul(c,res); 26 for (int j=0;j<9;j++) c=mat_mul(c,tmp); 27 } 28 return res.a[1][0]%mod; 29 } 30 int main(){ 31 scanf("%lld%lld%lld%lld",&x0,&x1,&a,&b); 32 scanf("%s",&n); 33 scanf("%lld",&mod); 34 ll ans=mat_pow(); 35 printf("%lld\n",ans); 36 return 0; 37 }
F.maximum clique 1
传送:https://ac.nowcoder.com/acm/contest/885/F
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #include<queue> 6 #define mem(a,b) memset(a,b,sizeof a) 7 #define en '\n' 8 #define maxn 5123 9 using namespace std; 10 typedef long long ll; 11 template<class T>void rd(T &x) 12 { 13 x=0;int f=0;char ch=getchar(); 14 while(ch<'0'||ch>'9') {f|=(ch=='-');ch=getchar();} 15 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 16 x=f?-x:x; 17 return; 18 } 19 20 const int inf =1<<29; 21 int head[maxn]; 22 int n,m,tot,maxflow,s,t,a[maxn]; 23 queue<int>q; 24 int d[maxn]; 25 struct node{ 26 int v,nxt,w; 27 }edge[80*maxn]; 28 29 void add(int u,int v,int w){ 30 edge[++tot].nxt=head[u];head[u]=tot;edge[tot].v=v;edge[tot].w=w; 31 edge[++tot].nxt=head[v];head[v]=tot;edge[tot].v=u;edge[tot].w=0; 32 } 33 bool bfs(){ 34 mem(d,0); 35 while(q.size())q.pop(); 36 q.push(s); 37 d[s]=1; 38 while(q.size()){ 39 int x=q.front();q.pop(); 40 for(int i=head[x];i;i=edge[i].nxt){ 41 if(edge[i].w and !d[edge[i].v]){ 42 q.push(edge[i].v); 43 d[edge[i].v]=d[x]+1; 44 if(edge[i].v==t){ 45 return 1; 46 } 47 } 48 } 49 } 50 return 0; 51 } 52 int dinic(int x,int flow){ 53 if(x==t)return flow; 54 int rest=flow,k; 55 for(int i=head[x];i and rest ;i=edge[i].nxt){ 56 if(edge[i].w and d[edge[i].v]==d[x]+1){ 57 k=dinic(edge[i].v,min(rest,edge[i].w)); 58 if(!k)d[edge[i].v]=0; 59 edge[i].w-=k; 60 edge[i^1].w+=k; 61 rest-=k; 62 } 63 } 64 return flow -rest; 65 } 66 bool ok(int x,int y){ 67 int tem=x^y; 68 int cnt=0; 69 while(tem){ 70 if(tem&1)cnt+=1; 71 tem>>=1; 72 } 73 if(cnt==1)return 1; 74 return 0; 75 } 76 bool ji(int x){ 77 int res=0; 78 while(x){ 79 res+=(x&1); 80 x>>=1; 81 } 82 return res&1; 83 } 84 bool vis[maxn]; 85 bool zuo[maxn]; 86 signed main() 87 { 88 #ifdef local 89 freopen("input2.txt","r",stdin); 90 #endif 91 int T; 92 //cin>>T; 93 T=1; 94 int cas=0; 95 while(T--){ 96 while(cin>>n){ 97 tot=1; 98 mem(edge,0); 99 mem(head,0); 100 ///___________________________________ 101 s=5001; 102 t=5002; 103 for(int i=1;i<=n;i++){ 104 rd(a[i]); 105 } 106 for(int i=1;i<=n;i++){ 107 for(int j=i+1;j<=n;j++){ 108 if(ok(a[i],a[j])){ 109 if(ji(a[i])) 110 add(i,j,inf); 111 else add(j,i,inf); 112 } 113 } 114 } 115 for(int i=1;i<=n;i++){ 116 if(ji(a[i])){ 117 zuo[i]=1; 118 add(s,i,1); 119 }else{ 120 add(i,t,1); 121 } 122 } 123 124 ///___________________________________ 125 int flow=0; 126 maxflow=0; 127 while(bfs()){ 128 while(flow=dinic(s,inf))maxflow+=flow; 129 } 130 cout<<n-maxflow<<en; 131 for(int i=1;i<=n;i++){ 132 if(zuo[i] and d[i]){ 133 cout<<a[i]<<' '; 134 } 135 if(!zuo[i] and !d[i]){ 136 cout<<a[i]<<' '; 137 } 138 }cout<<en; 139 } 140 } 141 return 0; 142 }
G.subsequence 1
传送:https://ac.nowcoder.com/acm/contest/885/G
题意:给定两个数字字符串$s$和$t$,求解$s$串内有多少个子序列大于$t$。答案$%998244353$。
数据范围:$1<=m<=n<=3000$。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=3050; 5 const ll mod=998244353; 6 int n,m; 7 ll ans; 8 char S[maxn],T[maxn]; 9 ll ini[maxn][maxn],sum[maxn][maxn],tag[maxn]; 10 void init() 11 { 12 ini[0][0]=1; 13 for (int i=1;i<=3000;i++) 14 { 15 ini[i][i]=ini[i][0]=1; 16 for (int j=1;j<i;j++) 17 { 18 ini[i][j]=(ini[i-1][j]+ini[i-1][j-1])%mod; 19 sum[i][j]=(sum[i][j-1]+ini[i][j])%mod; 20 } 21 sum[i][i]=(ini[i][i]+sum[i][i-1])%mod; 22 } 23 } 24 void initt() 25 { 26 ans=0; 27 memset(tag,0,sizeof(tag)); 28 tag[0]=1; 29 } 30 void solve() 31 { 32 initt(); 33 for (int i=1;i<=m;i++) 34 { 35 for (int j=n;j>=1;j--) 36 { 37 if(S[i]>T[j]) 38 {if(m-i>=n-j) ans=(ans+ini[m-i][n-j]*tag[j-1])%mod; } 39 else if(S[i]==T[j]) 40 {if(m-i>=n-j) tag[j]=(tag[j]+tag[j-1])%mod;} 41 } 42 } 43 for (int i=1;i<=m;i++) 44 if(m-i>=n && S[i]>'0') 45 { 46 ll tmp=sum[m-i][m-i]-sum[m-i][n-1]; 47 ans=((ans+tmp)%mod+mod)%mod; 48 } 49 printf("%lld\n",ans); 50 } 51 int main() 52 { 53 init(); 54 int t;scanf("%d",&t); 55 while (t--) 56 { 57 scanf("%d%d",&m,&n); 58 scanf("%s",S+1);scanf("%s",T+1); 59 solve(); 60 } 61 return 0; 62 }
H.subsequence 2
传送:https://ac.nowcoder.com/acm/contest/885/H
题意:有一个目标字符串,每次给定一个字符串$s$,然后可以得到一个长度为$m$的字符串$t$,代表$s$串内所有字母在目标字符串内出现的情况。求解目标字符串。
数据范围:$1<=n<=10^4,2<=m<=10,0<=len<=n$。
分析:建图+topo排序。考虑若干个字母出现的相对位置,有一个先后关系,建图,然后跑一个topo序。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e4; 4 char a[maxn+1000]; 5 map<char,int> mp; 6 int f[30],ans[maxn+1000],tag[30]; 7 bool flag; 8 int head[26*maxn+1000],ind[26*maxn+1000]; 9 int tot,n,m; 10 struct node{int u,v,nxt;} g[26*maxn+1000]; 11 void add(int u,int v) 12 { 13 g[tot]={u,v,head[u]}; 14 head[u]=tot++; 15 } 16 17 int cal() 18 { 19 int res=0; 20 queue<int> Q; 21 for (int i=0;i<26;i++) 22 for (int j=1;j<=tag[i];j++) 23 if(!ind[i*maxn+j]) {Q.push(i*maxn+j);ans[++res]=i;} 24 while (!Q.empty()) 25 { 26 int x=Q.front();Q.pop(); 27 // cout<<x<<endl; 28 for (int i=head[x];i;i=g[i].nxt) 29 { 30 int y=g[i].v;ind[y]--; 31 // cout<<y<<' '<<ind[y]<<endl; 32 if(!ind[y]) {ans[++res]=y/maxn;Q.push(y);} 33 } 34 } 35 // cout<<res<<endl; 36 return res; 37 } 38 void update() 39 { 40 mp.clear(); 41 scanf("%s",a); 42 int st=strlen(a); 43 for (int i=0;i<st;i++) mp[a[i]]++; 44 int x;scanf("%d",&x); 45 if(!x) return; 46 scanf("%s",a); 47 for (int i=0;i<30;i++) f[i]=0; 48 for (int i=0;i<x;i++) 49 { 50 if(mp[a[i]]==0) flag=false; 51 f[a[i]-'a']++; 52 if(i==0) continue; 53 if(a[i-1]!=a[i]) 54 { 55 int x1=(a[i-1]-'a')*maxn+f[a[i-1]-'a']; 56 int x2=(a[i]-'a')*maxn+f[a[i]-'a']; 57 add(x1,x2); 58 ind[x2]++; 59 } 60 } 61 for (int i=0;i<26;i++) 62 { 63 if(f[i] && !tag[i]) tag[i]=f[i]; 64 else if(f[i] && f[i]!=tag[i]) flag=false; 65 } 66 } 67 void solve() 68 { 69 int tmp=0; 70 for (int i=0;i<26;i++) 71 { 72 tmp+=tag[i]; 73 for (int j=1;j<tag[i];j++) 74 { 75 int xx=i*maxn+j; 76 add(xx,xx+1); 77 ind[xx+1]++; 78 } 79 } 80 if(tmp!=n) flag=false; 81 // for (int i=1;i<=tot;i++) cout<<i<<' '<<head[i]<<' '<<g[i].v<<endl; 82 if(!flag) {printf("-1\n");return;} 83 84 int sum=cal(); 85 if(sum!=n) {printf("-1\n");return;} 86 for (int i=1;i<=sum;i++) printf("%c",(char)ans[i]+'a'); 87 printf("\n");return; 88 } 89 int main() 90 { 91 scanf("%d%d",&n,&m); 92 int kk=(m-1)*m/2; 93 flag=true;tot=1; 94 while (kk--) update(); 95 solve(); 96 return 0; 97 }
I.three points 1
传送:https://ac.nowcoder.com/acm/contest/885/I
题意:构造三个点$X,Y,Z$,且满足条件:$|XY|=a,|XZ|=b,|YZ|=c,0<=x<=w,0<=y<=h$。
分析:考虑一个三角形能够在一个矩形内能够放下的所有情况。即固定一个点然后考虑另外两个点的位置。
枚举所有情况即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const double eps=1e-8; 4 int sgn(double x){ 5 if (fabs(x)<eps) return 0; 6 if (x<0) return -1; 7 return 1; 8 } 9 struct point{ 10 double x,y; 11 point(){} 12 point(double _x,double _y){ 13 x=_x; y=_y; 14 } 15 }aa[5]; 16 double w,h,a,b,c; 17 bool check(point z){ 18 if (sgn(z.x-0)>=0 && sgn(z.x-w)<=0 && sgn(z.y-0)>=0 && sgn(z.y-h)<=0) return true; 19 return false; 20 } 21 int solve(double a,double b,double c,int x,int y,int z){ 22 aa[x]=point(0.0,0.0); 23 if (a<=w) aa[y]=point(a,0.0); 24 else{ 25 double kk=sqrt(a*a-w*w); 26 aa[y]=point(w,kk); 27 } 28 double d=(a*a+b*b-c*c)/(2*a*b); 29 d=acos(d); 30 double dd=atan(aa[y].y/aa[y].x); 31 d+=dd; 32 aa[z]=point(b*cos(d),b*sin(d)); 33 if (check(aa[z])){ 34 for (int i=1;i<=3;i++){ 35 if(i!=3) printf("%.12f %.12f ",aa[i].x,aa[i].y); 36 else printf("%.12f %.12f\n",aa[i].x,aa[i].y); 37 } 38 return 1; 39 } 40 return 0; 41 } 42 int main(){ 43 int t;scanf("%d",&t); 44 while (t--){ 45 scanf("%lf%lf%lf%lf%lf",&w,&h,&a,&b,&c); 46 //枚举六种可能 47 if (solve(a,b,c,1,2,3)) continue; 48 if (solve(a,c,b,2,1,3)) continue; 49 if (solve(b,a,c,1,3,2)) continue; 50 if (solve(b,c,a,3,1,2)) continue; 51 if (solve(c,a,b,2,3,1)) continue; 52 if (solve(c,b,a,3,2,1)) continue; 53 } 54 return 0; 55 }