用户工具

站点工具


2020-2021:teams:wangzai_milk:20200513比赛记录

差别

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

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
2020-2021:teams:wangzai_milk:20200513比赛记录 [2020/05/18 18:33]
zars19 [A-Blank]
2020-2021:teams:wangzai_milk:20200513比赛记录 [2020/06/08 14:23] (当前版本)
wzx27
行 2: 行 2:
  
 ===== 比赛情况 ===== ===== 比赛情况 =====
 +
 +^题号 ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M |
 +^状态 |Ø |O |- |O |O |Ø |- |- |Ø |- |- |Ø |Ø |
 +
 +//O 在比赛中通过 Ø 赛后通过 ! 尝试了但是失败了 - 没有尝试//​
 +
 **比赛时间** **比赛时间**
  
行 24: 行 30:
 ==== A-Blank ==== ==== A-Blank ====
  
-solved ​by Zars19+补题 ​by Zars19
  
 code:​[[HDU6578]] code:​[[HDU6578]]
行 505: 行 511:
 </​code>​ </​code>​
  
 +==== L-Sequence ====
 +补题 by _wzx27
 +
 +把数列 $a_i$ 写成其生成函数的形式 $f(x)=\sum a_ix^i$,每个操作 $k$ 相当于 $f(x)\cdot \sum x^{ik}$,由交换律知顺序不重要,所以可以统计每种操作的次数 $m_i$,最后有
 +
 +$$f(x)\cdot (\sum x^{i})^{m_1} \cdot (\sum x^{2i})^{m_2} \cdot (\sum x^{3i})^{m_3}$$
 +
 +其中$(\sum x^{ki})^m = \sum {i+m-1 \choose m-1}x^{ik}$
 +
 +另外模数刚好是998244353,做三次NTT即可
 +
 +<hidden code>
 +<code cpp>
 +#​include<​bits/​stdc++.h>​
 +#define ll long long
 +#define pii_ pair<​int,​int>​
 +#define mp_ make_pair
 +#define pb push_back
 +#define fi first
 +#define se second
 +#define rep(i,a,b) for(int i=(a);​i<​=(b);​i++)
 +#define per(i,a,b) for(int i=(a);​i>​=(b);​i--)
 +#define show1(a) cout<<#​a<<"​ = "<<​a<<​endl
 +#define show2(a,b) cout<<#​a<<"​ = "<<​a<<";​ "<<#​b<<"​ = "<<​b<<​endl
 +using namespace std;
 +const ll INF = 1LL<<​60;​
 +const int inf = 1<<​30;​
 +const int maxn = 2e6+5;
 +const ll M = 998244353;
 +inline void fastio() {ios::​sync_with_stdio(false);​cin.tie(0);​cout.tie(0);​}
 +ll qpow(ll a,ll b) {ll s=1;​while(b){if(b&​1)s=(s*a)%M;​a=(a*a)%M;​b>>​=1;​}return s; }
 +int n,​m,​lim,​l,​r[maxn],​cnt[maxn];​
 +ll A[maxn],​B[maxn],​fac[maxn],​inv[maxn];​
 +int c[5];
 +void NTT(ll a[],int type)
 +{
 +    rep(i,​1,​lim-1) if(i<​r[i]) swap(a[i],​a[r[i]]);​
 +    for(int mid=1;​mid<​lim;​mid<<​=1){
 +        ll wn = qpow(3,​(M-1)/​mid/​2);​
 +        if(type==-1) wn = qpow(wn,​M-2);​
 +        for(int R=mid<<​1,​j=0;​j<​lim;​j+=R){
 +            ll w = 1;
 +            for(int k=0;​k<​mid;​k++,​w=w*wn%M){
 +                ll x=a[j+k],​y=w*a[j+mid+k]%M;​
 +                a[j+k] = (x+y)%M;
 +                a[j+mid+k] = (x-y+M)%M;
 +            }
 +        }
 +    }
 +    if(type==-1){
 +        ll INV = qpow(lim,​M-2);​
 +        rep(i,​0,​lim) a[i] = a[i]*INV%M;
 +    }
 +}
 +ll Comb(ll a,ll b) {return a<​b?​0:​fac[a]*inv[b]%M*inv[a-b]%M;​}
 +void init()
 +{
 +    fac[0] = 1;
 +    rep(i,​1,​2000000) fac[i]=fac[i-1]*i%M;​
 +    inv[2000000] = qpow(fac[2000000],​M-2);​
 +    per(i,​2000000-1,​0) inv[i]=inv[i+1]*(i+1)%M;​
 +}
 +int main()
 +{
 +    fastio();
 +    int _;
 +    init();
 +    for(cin>>​_;​_;​_--){
 +        cin>>​n>>​m;​
 +        memset(A,​0,​sizeof(A));​
 +        memset(B,​0,​sizeof(B));​
 +        rep(i,​0,​n-1) cin>>​A[i];​
 +        lim=1,l=0;
 +        while(lim<​=2*n) lim<<​=1,​l++;​
 +        rep(i,​0,​lim-1) r[i] = (r[i>>​1]>>​1) | ((i&​1)<<​(l-1));​
 +        cnt[1]=cnt[2]=cnt[3]=0;​
 +        while(m--) {int x;​cin>>​x;​cnt[x]++;​}
 +        rep(i,​1,​3)if(cnt[i]){
 +            memset(B,​0,​sizeof(B));​
 +            for(int j=0;​j*i<​n;​j++) B[i*j] = Comb(cnt[i]+j-1,​j);​
 +            NTT(A,​1);​NTT(B,​1);​
 +            rep(i,​0,​lim) A[i] = A[i]*B[i]%M;​
 +            NTT(A,-1);
 +            rep(i,​n+1,​lim) A[i]=0;
 +        }
 +        ll ans = 0;
 +        rep(i,​0,​n-1) ans ^= ((i+1)*A[i]);​
 +        cout<<​ans<<​endl;​
 +    }
 +    return 0;
 +}
 +</​code>​
 +</​hidden>​
 +
 +==== M-Code ====
 +补题 by Zars19
 +
 +[[http://​acm.hdu.edu.cn/​showproblem.php?​pid=6590|M-Code]]
 +
 +code:
 +<​hidden>​
 +<code cpp>
 +#​include<​iostream>​
 +#​include<​cstdio>​
 +#​include<​cstring>​
 +#​include<​cstdlib>​
 +#​include<​cmath>​
 +#​include<​algorithm>​
 +#define LL long long
 +#define INF 0x3f3f3f3f
 +#define eps 1e-10
 +using namespace std;
 +const int N=105;
 +int read()
 +{
 + int x=0,​f=1;​char c=getchar();​
 + while(c<'​0'​||c>'​9'​){if(c=='​-'​)f=-1;​c=getchar();​}
 + while(c>​='​0'&&​c<​='​9'​){x=x*10+c-'​0';​c=getchar();​}
 + return x*f;
 +}
 +int dcmp(double x){return x<​-eps?​-1:​(x>​eps);​}
 +struct Point
 +{
 + double x,y;
 + Point(double x=0,double y=0):​x(x),​y(y){}
 + Point operator + (Point a){return Point(x+a.x,​y+a.y);​}
 + Point operator - (Point a){return Point(x-a.x,​y-a.y);​}
 + Point operator * (double a){return Point(a*x,​a*y);​}
 + bool operator == (Point a){return dcmp(x-a.x)==0&&​dcmp(y-a.y)==0;​}
 +}d1[N],​d2[N],​p;​
 +int top1,top2;
 +typedef Point Vector;
 +double sqr(double x){return x*x;}
 +double Cross(Vector v1,Vector v2){return v1.x*v2.y-v1.y*v2.x;​}
 +double Dot(Vector v1,Vector v2){return v1.x*v2.x+v1.y*v2.y;​}
 +double dissqr(Point p1,Point p2){return sqr(p1.x-p2.x)+sqr(p1.y-p2.y);​}
 +bool cmp(Point p1, Point p2)
 +{
 + int u=dcmp(Cross(p1-p,​p2-p));​
 + return u>​0||(u==0&&​dcmp(dissqr(p1,​p)-dissqr(p2,​p))<​0);​
 +}
 +int Graham(Point *d,int n)
 +{
 + int k=0;
 + for(int i=0;​i<​n;​i++)
 + {
 + int u=dcmp(d[i].x-d[k].x);​
 + int v=dcmp(d[i].y-d[k].y);​
 + if(v<​0||(v==0&&​u<​0))k=i;​
 + }
 + p=d[k];
 + sort(d,​d+n,​cmp);​
 + n=unique(d,​d+n)-d;​
 + if(n<​=1)return n;
 + if(dcmp(Cross(d[n-1]-d[0],​d[1]-d[0]))==0){d[1]=d[n-1];​return 2;}
 + d[n++]=d[0];​
 + int m=1;
 + for(int i=2;​i<​n;​i++)
 + {
 + while(m>​0&&​dcmp(Cross(d[m]-d[m-1],​d[i]-d[m-1]))<​=0)m--;​
 + d[++m]=d[i];​
 + }
 + return m;
 +}
 +bool SegInter(Point p1,Point p2,Point p3,Point p4)
 +{
 + if(max(p1.x,​p2.x)<​min(p3.x,​p4.x))return 0;
 + if(max(p3.x,​p4.x)<​min(p1.x,​p2.x))return 0;
 + if(max(p1.y,​p2.y)<​min(p3.y,​p4.y))return 0;
 + if(max(p3.y,​p4.y)<​min(p1.y,​p2.y))return 0;
 + int u=dcmp(Cross(p2-p1,​p3-p1))*dcmp(Cross(p2-p1,​p4-p1));​
 + int v=dcmp(Cross(p4-p3,​p1-p3))*dcmp(Cross(p4-p3,​p2-p3));​
 + return u<​=0&&​v<​=0;​
 +}
 +double TriS(Point p1,Point p2,Point p3){return fabs(Cross(p2-p1,​p3-p1)/​2);​}
 +bool InTri(Point p1,Point p2,Point p3,Point p0)
 +{
 + double s1=TriS(p1,​p2,​p0),​s2=TriS(p1,​p3,​p0),​s3=TriS(p2,​p3,​p0),​s=TriS(p1,​p2,​p3);​
 + return dcmp(s-s1-s2-s3)==0;​
 +}
 +int main()
 +{
 + int T=read();
 + while(T--)
 + {
 + top1=top2=0;​
 + int n=read();
 + for(int i=1;​i<​=n;​i++)
 + {
 + int x1=read(),​x2=read(),​y=read();​
 + if(y<​0)d1[top1++]=Point(x1,​x2);​
 + else d2[top2++]=Point(x1,​x2);​
 + }
 + top1=Graham(d1,​top1);​
 + top2=Graham(d2,​top2);​
 + bool f=1;
 + for(int i=0;​i<​top1&&​f;​i++)
 + for(int j=0;​j<​top2&&​f;​j++)
 + if(SegInter(d1[i],​d1[(i+1)%top1],​d2[j],​d2[(j+1)%top2]))f=0;​
 + for(int i=0;​i<​top1&&​f;​i++)
 + for(int j=1;​j<​top2-1&&​f;​j++)
 + if(InTri(d2[0],​d2[j],​d2[j+1],​d1[i]))f=0;​
 + if(f)puts("​Successful!"​);​
 + else puts("​Infinite loop!"​);​
 + }
 + return 0;
 +}
 +</​code>​
 +</​hidden>​
 +\\
 +
 +给出一个集合,集合中元素是$(\boldsymbol{x_i},​y_i)$,其中$\boldsymbol{x_i}$是一个$d$维向量,本题中$d=2$。$f(\boldsymbol{x})=sign(\sum^d_{i=1}w_i⋅x_i+b)=sign(\boldsymbol{w^T}⋅\boldsymbol{x}+b)$。问有没有一个向量$\boldsymbol{w}$可以使得所有$f(\boldsymbol{x_i})=y_i$。
 +
 +题解:这题读题好难。。其实是计算几何,判断凸包是否相交。$x_1w_1+x_2w_2+b=0$是二维平面上的一条直线,一侧使得$f(\boldsymbol{x_i})$为$1$,另一侧为$-1$。问题转化成有没有一条直线可以把两个点集分开,于是又等价于对两个点集求凸包判断是否相交。判断凸包相交可以$O(n^2)$做,先判两凸包上的边两两是否线段相交,再看一凸包中的每一个顶点是否在另一凸包内。
  
 ===== replay ===== ===== replay =====
2020-2021/teams/wangzai_milk/20200513比赛记录.1589797998.txt.gz · 最后更改: 2020/05/18 18:33 由 zars19