队内ACM赛

Posted olm2598827139

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了队内ACM赛相关的知识,希望对你有一定的参考价值。

T1 心灵终结

打表找规律。。。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 long long T,n,m;
 8 
 9 long long solve(long long x){
10     if(x%4==0)return x;
11     if(x%4==1)return x+1;
12     if(x%4==2)return x+2;
13     if(x%4==3)return x+1;
14 }
15 
16 int main(){
17     scanf("%lld",&T);
18     while(T--){
19         scanf("%lld%lld",&n,&m);
20         if(m==1||n==1)printf("%lld
",m*n);
21         else if(n==2)printf("%lld
",solve(m));
22         else if(m==2)printf("%lld
",solve(n));
23         else printf("%lld
",(n*m+1)/2); 
24     }
25     return 0;
26 }

 

T2 Super Big Stupid Cross

排序竟然能暴力水过??

正解好像是二分、扫描线加平衡树乱搞吧

反正我不会正解。。。

 

#include<cstdio>
#include<algorithm>
using namespace std;
#pragma GCC optimize(2)

int n,ans,sum1,sum2;
struct oo{int x1,y1,x2,y2,len;}f[100001],g[100001];

bool cmp(oo a,oo b){return a.len>b.len;}

int main(){
    scanf("%d",&n);
    for(int i=1,a,b,c,d;i<=n;i++){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        if(a>c)swap(a,c);if(b>d)swap(b,d);
        if(a==c)f[++sum1]=(oo){a,b,c,d,abs(b-d)};
        else g[++sum2]=(oo){a,b,c,d,abs(a-c)};
    }
    sort(f+1,f+sum1+1,cmp);
    sort(g+1,g+sum2+1,cmp);
    for(int i=1;i<=sum1;i++){
        if((ans<<1)>=f[i].len)break;
        for(int j=1;j<=sum2;j++){
            if((ans<<1)>=g[j].len)break;
            ans=max(ans,min(min(g[j].y1-f[i].y1,f[i].y2-g[j].y1),min(g[j].x2-f[i].x1,f[i].x1-g[j].x1)));
        }
    }
    if(!ans)printf("Human intelligence is really terrible
");
    else printf("%d
",ans);
}

 

T3 Baby Step

这题用并查集维护一下连通性就好了

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=510,inf=1e9;
 5 
 6 int n,m,f[N*N],p;
 7 
 8 int read(){int x=0,f=1;char c=getchar();
 9     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
10     while(c<=9&&c>=0){x=x*10+c-0;c=getchar();}
11     return x*f;
12 }
13 
14 int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
15 
16 int num(int x,int y){
17     if(x<1||y<1||x==n||y==n)return 0;
18     else return (x-1)*n+y;
19 }
20 
21 void get(int x,int y){
22     int fx=find(x),fy=find(y);
23     if(fx==fy)puts("DAJIA"),p=1;
24     else f[fy]=fx,p=0,puts("HAHA");
25 }
26 
27 int main(){
28     int x1,y1,x2,y2;
29     n=read();m=read();
30     for(int i=0;i<=n*n;i++)f[i]=i;
31     for(int i=1;i<=m;i++){
32         x1=read();y1=read();x2=read();y2=read();
33         if(i>1)
34             if(p)x1=read(),y1=read(),x2=read(),y2=read();
35             else for(int i=1;i<5;i++)int t=read();
36         if(x1>x2)swap(x1,x2);if(y1>y2)swap(y1,y2);
37         if(x1<x2){
38             int x=num(x1,y1-1),y=num(x1,y1);
39             get(x,y);
40         }
41         else{
42             int x=num(x1-1,y1),y=num(x1,y1);
43             get(x,y);
44         }
45     }
46 }

 

T4 压位

高精度+DP

这个DP我以前写过,是USACO的一道原题

这题题目范围很小,可以不像USACO那样优化到(O(n))

(f[i]) 代表做到第(i)位没有连续的(>=k)的方案总数

DP方程为:

$$ f[i]=sum_{j=i-k+1}^{i-1}f[j]*(d-1) $$

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4  
  5 int read()
  6 {
  7   int x=0,f=1;
  8   char ch=getchar();
  9   while((ch<0)||(ch>9))
 10     {
 11       if(ch==-)
 12         {
 13           f=-f;
 14         }
 15       ch=getchar();
 16     }
 17   while((ch>=0)&&(ch<=9))
 18     {
 19       x=x*10+ch-0;
 20       ch=getchar();
 21     }
 22   return x*f;
 23 }
 24  
 25 const int maxn=8000;
 26 const int maxm=100;
 27  
 28 struct bignum
 29 {
 30   int val[maxn+10];
 31  
 32   int clear()
 33   {
 34     memset(val,0,sizeof val);
 35     return 0;
 36   }
 37 };
 38  
 39 bignum operator +(const bignum &a,const bignum &b)
 40 {
 41   bignum res;
 42   res.val[0]=std::max(a.val[0],b.val[0]);
 43   int r=0;
 44   for(int i=1; i<=res.val[0]; ++i)
 45     {
 46       res.val[i]=((i>a.val[0])?0:a.val[i])+((i>b.val[0])?0:b.val[i])+r;
 47       r=res.val[i]>>1;
 48       res.val[i]&=1;
 49     }
 50   if(r>0)
 51     {
 52       res.val[++res.val[0]]=r;
 53     }
 54   return res;
 55 }
 56  
 57 bignum operator *(const bignum &a,const int &b)
 58 {
 59   bignum res;
 60   res.val[0]=a.val[0];
 61   int r=0;
 62   for(int i=1; i<=a.val[0]; ++i)
 63     {
 64       res.val[i]=a.val[i]*b+r;
 65       r=res.val[i]>>1;
 66       res.val[i]&=1;
 67     }
 68   while(r)
 69     {
 70       res.val[++res.val[0]]=r&1;
 71       r>>=1;
 72     }
 73   return res;
 74 }
 75  
 76 bignum operator *(const bignum &a,const bignum &b)
 77 {
 78   bignum res;
 79   res.clear();
 80   res.val[0]=a.val[0]+b.val[0]-1;
 81   for(int i=1; i<=a.val[0]; ++i)
 82     {
 83       int r=0;
 84       for(int j=1; j<=b.val[0]; ++j)
 85         {
 86           int k=i+j-1;
 87           res.val[k]+=a.val[i]*b.val[j]+r;
 88           r=res.val[k]>>1;
 89           res.val[k]&=1;
 90         }
 91       if(r)
 92         {
 93           res.val[i+b.val[0]]=r;
 94           if(i+b.val[0]>res.val[0])
 95             {
 96               res.val[0]=i+b.val[0];
 97             }
 98         }
 99     }
100   return res;
101 }
102  
103 bignum f[maxm+10],ans;
104 int d,q,n,k;
105  
106 int main()
107 {
108   d=read();
109   q=read();
110   n=read();
111   k=read();
112   f[0].val[0]=f[0].val[1]=1;
113   for(int i=1; i<k; ++i)
114     {
115       f[i]=f[i-1]*d;
116     }
117   for(int i=k; i<=n; ++i)
118     {
119       bignum sum;
120       sum.clear();
121       for(int j=i-k+1; j<i; ++j)
122         {
123           sum=sum+f[j];
124         }
125       f[i]=sum*(d-1);
126     }
127   ans.val[0]=ans.val[1]=1;
128   for(int i=1; i<=q; ++i)
129     {
130       ans=ans*f[n];
131     }
132   printf("%d
",ans.val[0]-1);
133   return 0;
134 }

 

T5 公共子序列

DP模板最长公共子序列求第(1)问

然后求第(2,3)问就在原来的DP方程后面加一维(len)

第(2,3)问就能同时求出来了

 

 1 #pragma GCC optimize(2)
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 
 9 const int N=305,P=1<<20;
10 
11 int n,m;char s1[N],s2[N];
12 int mx,sum,ans[N],las1[N],las2[N],last[N];
13 int f[N][N],g[N][N][N];
14 
15 int main(){
16     scanf("%s%s",s1+1,s2+1);
17     n=strlen(s1+1),m=strlen(s2+1);
18     for(int i=1;i<=n;++i)
19         for(int j=1;j<=m;++j){
20             f[i][j]=max(f[i][j],f[i-1][j]);
21             f[i][j]=max(f[i][j],f[i][j-1]);
22             if(s1[i]==s2[j])f[i][j]=max(f[i][j],f[i-1][j-1]+1);
23         }
24     mx=f[n][m];
25     printf("%d
",f[n][m]);
26     for(int i=1;i<=n;++i)
27         las1[i]=last[s1[i]],last[s1[i]]=i;
28     memset(last,0,sizeof last);
29     for(int i=1;i<=m;++i)
30         las2[i]=last[s2[i]],last[s2[i]]=i;
31     for(int i=0;i<=n;++i)
32         for(int j=0;j<=m;++j)g[i][j][0]=1;
33     for(int i=1;i<=n;++i)
34         for(int j=1;j<=m;++j)
35         if(s1[i]==s2[j]){
36             for(int k=1;k<=mx;++k){
37                 g[i][j][k]=(g[i-1][j-1][k]+g[i-1][j-1][k-1])%P;
38                 if(las1[i]&&las2[j])
39                     g[i][j][k]=(g[i][j][k]-g[las1[i]-1][las2[j]-1][k-1]+P)%P;
40             }
41         }
42         else
43             for(int k=1;k<=mx;++k)
44                 g[i][j][k]=(g[i-1][j][k]+g[i][j-1][k]+P-g[i-1][j-1][k])%P;
45     for(int i=1;i<=mx;++i)
46         sum=(sum+g[n][m][i])%P;
47     printf("%d
",sum);
48     for(int i=1;i<=mx;++i)
49         printf("%d
",g[n][m][i]);
50     return 0;
51 }

 

T6

扫描线加线段树

要维护这个三元组

线段树要维护区间和还有区间最大值

 

以上是关于队内ACM赛的主要内容,如果未能解决你的问题,请参考以下文章

队内赛 T3区间DP大哥扛纵连

队内赛T1贪心日常

队内赛 T1数学暴力多项式滚出OI

2018ACM-ICPC亚洲区域赛南京站I题Magic Potion(网络流)

2022.2.27 队内个人训练赛(上)

luogu 11.8 队内赛 暴力T1 Lyrith -迷宮リリス-