用户工具

站点工具


2020-2021:teams:die_java:front_page_summertrain2

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
2020-2021:teams:die_java:front_page_summertrain2 [2020/07/17 17:51]
mychael
2020-2021:teams:die_java:front_page_summertrain2 [2020/10/17 23:02] (当前版本)
fyhssgss
行 11: 行 11:
 ===== 题解 ===== ===== 题解 =====
  
-===== 题目名字 ​=====+===== B.Boundary ​=====
  
 === 题意 === === 题意 ===
 +
 +给了n个点,画一个过原点的圆,问最多能有多少个点在圆上。
  
 === 题解 === === 题解 ===
  
 +我们固定原点和一个点,枚举剩下的点,求出这三个点的圆心,答案即为重合最多的圆心数加一。题目有点卡常,用分数计算会超时,无奈只能用double记录点玄学通过。
 +
 +<hidden 代码>
 <code cpp> <code cpp>
 +#​include<​bits/​stdc++.h>​
 +using namespace std;
 +#define mem(a,b) memset(a,​b,​sizeof(a))
 +typedef long long LL;
 +typedef pair<​LL,​LL>​ PII;
 +typedef pair<​double,​double>​ PDD;
 +#define X first
 +#define Y second
 +inline int read()
 +{
 +    int x=0,​f=1;​char c=getchar();​
 +    while(!isdigit(c)){if(c=='​-'​)f=-1;​c=getchar();​}
 +    while(isdigit(c)){x=x*10+c-'​0';​c=getchar();​}
 +    return x*f;
 +}
  
 +const int N=2000055;
 +const int maxn=2010;
 +PII A[maxn];
 +LL aa[N];
 +int n,ans,sum;
 +map<​PDD,​int>​ mp;
 +LL gcd(LL a,LL b){return b==0 ? a : gcd(b,​a%b);​}
 +int main()
 +{
 +    n=read();
 +    for(int i=1;​i<​=n;​i++)scanf("​%lld%lld",&​A[i].X,&​A[i].Y);​
 +    for(int i=1;​i<​n;​i++)
 +    {
 +        mp.clear();
 +        for(int j=i+1;​j<​=n;​j++)
 +        {
 +            LL a=A[i].X,​b=A[i].Y,​c=A[j].X,​d=A[j].Y;​
 +            if(b*c-a*d==0) continue;
 +            LL p=a*a+b*b,​q=c*c+d*d,​r=b*c-a*d;​
 +            LL x1=q*b-p*d,​x2=r;​
 +            LL y1=p*c-q*a,​y2=r;​
 +//          LL xx=gcd(abs(x1),​abs(x2)),​yy=gcd(abs(y1),​abs(y2));​
 +            double xx=1.*x1/​x2;​
 +            double yy=1.*y1/​y2;​
 +/*            if(x1<​0) ​  ​分数做法
 +            {
 +                x1*=-1;​x2*=-1;​
 +            }
 +            else if(x1==0)
 +            {
 +                x2=1;xx=1;
 +            }
 +            if(y1<0)
 +            {
 +                y1*=-1;​y2*=-1;​
 +            }
 +            else if(y1==0)
 +            {
 +                y2=1;yy=1;
 +            }
 +            x1/​=xx;​x2/​=xx;​y1/​=yy;​y2/​=yy;​
 +            LL hs2=0;
 +            hs2=hs2*998244353+x1;​hs2=hs2*998244353+x2;​
 +            hs2=hs2*998244353+y1;​hs2=hs2*998244353+y2;​
 +//          printf("​%d %d %lld %lld %lld %lld\n",​i,​j,​x1,​x2,​y1,​y2);​
 +//          aa[++sum]=hs2;​*/​
 +            ans=max(ans,​++mp[PDD(xx,​yy)]);​
 +        }
 +    }
 +/*  sort(aa+1,​aa+1+sum);​
 +    for(int i=1;​i<​=sum;​i++)
 +    {
 +        int tot=1;
 +        for(int j=i+1;​j<​=sum;​j++)
 +        {
 +            if(aa[j]==aa[i]) tot++;
 +            else break;
 +        }
 +        ans=max(ans,​tot);​
 +        i+=tot-1;
 +    }*/
 +     ​printf("​%d\n",​++ans);​
 +    return 0;
 +}
 </​code>​ </​code>​
 +</​hidden>​
 ===== C.Cover the Tree ===== ===== C.Cover the Tree =====
  
行 28: 行 112:
  
 === 题解 === === 题解 ===
 +
 +solved by hxm
  
 路径显然最优时从一个叶子出发,到另一个叶子结束。记叶子节点个数为$m$,那么答案应该就是$\lceil \frac{m}{2} \rceil$ 路径显然最优时从一个叶子出发,到另一个叶子结束。记叶子节点个数为$m$,那么答案应该就是$\lceil \frac{m}{2} \rceil$
行 153: 行 239:
 水题 水题
  
 +===== E.Exclusive OR =====
 +
 +=== 题意 ===
 +
 +给了 $n$ 个数,让你求 $1 \le i \le n$ ,选 $i$ 个数(可以选相同的数)异或和的最大值。
 +
 +=== 题解 ===
 +
 +发现 $i$ 在19之后答案和 $i-2$ 一致,原理参考线性基。所以我们只需求前19个的答案,用FWT即可完成。
 +
 +<hidden 代码>
 +<code cpp>
 +#​include<​iostream>​
 +#​include<​cstdio>​
 +#​include<​algorithm>​
 +#​include<​cstring>​
 +#define ll long long
 +using namespace std;
 +int read()
 +{
 +    int k=0,​f=1;​char c=getchar();​
 +    for(;​!isdigit(c);​c=getchar()) if(c=='​-'​) f=-1;
 +    for(;​isdigit(c);​c=getchar()) k=k*10+c-'​0';​return k*f;
 +}
 +const int M=1050000;
 +int n,​N,​a[M],​b[M],​c[M],​ans[M];​
 +void FWT(int *a,int opt)
 +{
 +    for(int i=1;​i<​N;​i<<​=1)
 +        for(int p=i<<​1,​j=0;​j<​N;​j+=p)
 +            for(int k=0;​k<​i;​++k)
 +            {
 +                int X=a[j+k],​Y=a[i+j+k];​
 +                a[j+k]=(X+Y);​a[i+j+k]=(X-Y);​
 +                if(opt==-1)a[j+k]=1ll*a[j+k]/​2,​a[i+j+k]=1ll*a[i+j+k]/​2;​
 +            }
 +}
 +int main()
 +{
 +    n=read();​int mx=0,x;
 +    for(int i=1;​i<​=n;​i++)
 +    {
 +        x=read();
 +        a[x]=1;​b[x]=1;​mx=max(mx,​x);​
 +    }
 +    for(N=1;​N<​=mx;​N<<​=1);​
 +    ans[1]=mx;
 +    FWT(b,1);
 +    for(int i=2;​i<​=min(25,​n);​i++)
 +    {
 +        for(int j=0;​j<​N;​j++)
 +            if(a[j]) a[j]=1;
 +        FWT(a,1);
 +        for(int j=0;​j<​N;​j++)
 +            a[j]=a[j]*b[j];​
 +        FWT(a,-1);
 +        for(int j=N-1;​j>​=0;​j--)
 +        {
 +            if(a[j]) {ans[i]=j;​break;​}
 +        }
 +//      for(int j=0;​j<​N;​j++)
 +//          cout<<​a[j]<<"​ ";
 +//      cout<<​endl;​
 +    }
 +    for(int i=1;​i<​=n;​i++)
 +    {
 +        if(i>​25) ​
 +        {
 +            if(i&1) printf("​%d ",​ans[25]);​
 +            else printf("​%d ",​ans[24]);​
 +        }
 +        else printf("​%d ",​ans[i]);​
 +    }
 +    puts(""​);​
 +    return 0;
 +}
 +</​code>​
 +</​hidden>​
 ===== F.Fake Maxpooling ===== ===== F.Fake Maxpooling =====
  
行 164: 行 328:
  
 === 题解 === === 题解 ===
 +
 +solved by hxm
  
 暴力$O(nmlogn)$求出$lcm$,然后竖着用$m$个单调队列维护最大值,然后再用一个单调队列维护单调队列的最大值,即可求出当前区域的最大值。 暴力$O(nmlogn)$求出$lcm$,然后竖着用$m$个单调队列维护最大值,然后再用一个单调队列维护单调队列的最大值,即可求出当前区域的最大值。
行 374: 行 540:
 </​code>​ </​code>​
 </​hidden>​ </​hidden>​
-===== 题目名字 ===== 
  
-=== 题意 === 
- 
-=== 题解 === 
- 
-<code cpp> 
- 
-</​code>​ 
 ===== J.Just Shuffle ===== ===== J.Just Shuffle =====
  
2020-2021/teams/die_java/front_page_summertrain2.1594979465.txt.gz · 最后更改: 2020/07/17 17:51 由 mychael