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 } 
A

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 }
B

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 }
F

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 }
G

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 }
H

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 } 
I

 

posted @ 2019-08-02 16:39  Changer-qyz  阅读(257)  评论(1编辑  收藏  举报