• 「2019.7.22 考试」AC和WA0一步之遥


    这卷子还是答的挺惨的。

    第一题5min写完了,自认为AC(其实WA了80),第二题推了半天CRT的公式老出错结果发现是程序打错了。第三题打模拟150行结果数组没开够,开大就是0->60的转变。状态很差,坏肚子了,一直在去厕所,看来下次早起要吃点素的了。

    题解:

    T1方程的解。

    发现就是个exgcd,先求出gcd和顺带的特解 $ x_0 y_0 $

    设 $ gcd(a,b)=d $

    这个时候用个通解公式:

    $ x=x_0 frac{c}{d} + k frac{b}{d} $

    $ y=y_0 frac{c}{d} - k frac{a}{d} $

    那么我们发现方程解的个数就是k的个数。

    解个不等式组:

    $ x>0 $

    $ y>0 $

    得到:

    $ y_0 frac{c}{a} < k <-x_0 frac{c}{b} $

    左边向下取整得到l,右边向上去整得到r。

    答案个数就是r-l+1,没必要暴力枚举验证啥的,稍low。

    加特判就AC,顺提这特判真恶心。

    T2 visit

    一眼数学题很准,式子推错了没办法。

    先说一下错解,大概是分的不太明确,没有把同类分到一组。

    设d=T-n-m。

    首先d>0并且2|d有解:

    我是按照到 $ (n,m) $ 的有效步和无效步算的,这样的话我推出来得式子就是:

    $ C_T^{n+m} C_{n+m}^n sum limits_{i=0,2|i}^d (C_d^i C_i^{frac{i}{2}} C_{d-i}^{frac{d-i}{2}}) $

    看一看他什么意思,我把有效的n+m步从T步里分了出来,然后把n步向上的从n+m步中分离开。

    剩下的就是d步中的上下左右插空,可以枚举上下走的步数,是i,可以证明他必然是偶数,然后这些步子中必然有 $ frac{i}{2} $ 步向上,在i步中选出相应的位置,剩下左右走的也可以选出相应的位置。

    我们看一下他哪里有问题,问题在于,前面分出来的n步中,是向上走的,他等同于无效步中向上走的步,但是却被我分开计算了。

    导致解变多。

    正解的话还简单一点,按照方向分布,这样不会出现和我一样的问题。

    也就是:

    $ sum limits_{d=n}^{T-m} C_T^d C_d^{frac{d-n}{2}} C_{T-d}^{frac{T-d-m}{2}} $

    还是比较简单的,不赘述。

    式子出来之后就只剩下板子了,质数小就Lucas算一下,质数多就CRT合并一下,解决了。

    T3的话是个大模拟。

    一些推论:

    1.一个方向上的格子奇偶性不变,所以一个格子最多被从两个相反方向的光射入。

    2.黑格子很少,一次循环中反射的次数和n,m,k线性相关。

    3.每一条主对角线和副对角线都有一个特殊的编号,可以用x+y和x-y+m来编号。

    4.每个格子在一次循环里最多被射两次,只需要记录是否存在反向操作,有的话答案除2。

    可以通过坐标二分查找到转角处。

    程序写的时候其实可以只写一个判断方向的函数,用这个函数找到他前面的格子,左边的格子和右边的格子,然后用pair存一下,换个函数只需要判断左转右转还是反向,只需要写左转右转反向的函数了,看起来多不过很好水。

    那就这么多。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    ll T,a,b,c,x,y;
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(b==0)
        {
            x=1;y=0;
            return a;
        }
        ll d=exgcd(b,a%b,x,y);
        ll tmp=x;
        x=y;
        y=tmp-a/b*y;
        return d;
    }
    int main()
    {
        scanf("%lld",&T);
        while(T--)
        {
            scanf("%lld%lld%lld",&a,&b,&c);
            ll d=exgcd(a,b,x,y);
            ll l=floor(1.0*c/b*(-x)),r=ceil(1.0*c/a*y);
            ll k=r-l-1;
            if(a==0&&b==0)
            {
                if(c==0)
                {
                    puts("ZenMeZheMeDuo");
                    continue;
                }
                else
                {
                    puts("0");
                    continue;
                }
            }
            if((c%d))
            {
                puts("0");
                continue;
            }
            if(1LL*a*b<0)
            {
                puts("ZenMeZheMeDuo");
                continue;
            }
            if(a==0)
            {
                if(1LL*b*c>0) puts("ZenMeZheMeDuo");
                else puts("0");
                continue;
            }
            if(b==0)
            {
                if(1LL*a*c>0) puts("ZenMeZheMeDuo");
                else puts("0");
                continue;
            }
            if(k<0)
            {
                puts("0");
                continue;
            }
            if(k>65535) puts("ZenMeZheMeDuo");
            else printf("%lld
    ",k);
        }
        return 0;
    }
    方程的解
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+5;
    ll T,mod,n,m,s,fac[maxn],inv[maxn],p[11],ans[11];
    ll qw(ll a,ll b,ll ml)
    {
        ll ans=1;
        for(;b;b>>=1,a=a*a%ml) if(b&1) ans=ans*a%ml;
        return ans;
    }
    void moddivide()
    {
        ll mm=mod;
        for(int i=2;1LL*i*i<=mm;i++)
            if(mm%i==0)
            {
                p[++s]=i;
                mm/=i;
            }
        if(mm>1) p[++s]=mm;
    }
    ll CRT()
    {
        ll b=0;
        for(int i=1;i<=s;i++)
        {
            ll M=mod/p[i];
            b+=ans[i]*M%mod*qw(M,p[i]-2,p[i])%mod;
            b%=mod;
        }
        return b;
    }
    void Getfac_inv(int p)
    {
        fac[0]=inv[0]=1;
        for(int i=1;i<=min(T,(ll)p);i++)
        {
            fac[i]=fac[i-1]*i%p;
            inv[i]=qw(fac[i],p-2,p);
        }
    }
    ll Get_C(ll n,ll m,ll mod)
    {
        if(n<m) return 0;
        return fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    ll lucas(ll n,ll m,ll p)
    {
        if(m==0) return 1;
        return Get_C(n%p,m%p,p)*lucas(n/p,m/p,p)%p;
    }
    int main()
    {
        scanf("%lld%lld",&T,&mod);
        scanf("%lld%lld",&n,&m);
        n=abs(n);m=abs(m);
        int d=T-n-m;
        if(d<0||(d&1))
        {
            puts("0");
            return 0;
        }
        moddivide();
        ll aa;
        for(int j=1;j<=s;j++)
        {
            Getfac_inv(p[j]);
            aa=0;
            for(int i=n;i<=T-m;i+=2)
            {
                ll tmp=lucas(T,i,p[j])*lucas(i,(i-n)/2,p[j])%p[j]*lucas(T-i,(T-i-m)/2,p[j])%p[j];
                aa+=tmp;
                aa%=p[j];
            }
            ans[j]=aa;
        }
        printf("%lld
    ",CRT());
        return 0;
    }
    visit
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    #include<map>
    #define mr(a,b) make_pair(a,b)
    using namespace std;
    typedef long long ll;
    const int ne=1,se=2,sw=3,nw=4,maxn=1e5+5,tmp=maxn+10;
    const int xi[5]={0,-1,+1,+1,-1},yi[5]={0,+1,+1,-1,-1};
    vector<int> man[maxn<<1],rst[maxn<<1];
    map<ll,int> mp;
    map<pair<int,pair<int,int> >,int> up;
    int n,m,k,x,y,sx,sy,nx,ny,fr,dr,flag;
    ll ans;
    char s[5];
    int jud()
    {
        if(s[1]=='N'&&s[2]=='E') return sw;
        if(s[1]=='N'&&s[2]=='W') return se;
        if(s[1]=='S'&&s[2]=='E') return nw;
        if(s[1]=='S'&&s[2]=='W') return ne;
    }
    int right(int x)
    {
        if(x==ne) return se;
        if(x==se) return sw;
        if(x==sw) return nw;
        if(x==nw) return ne;
    }
    int left(int x)
    {
        if(x==ne) return nw;
        if(x==nw) return sw;
        if(x==sw) return se;
        if(x==se) return ne;
    }
    int ni(int x)
    {
        if(x==ne) return sw;
        if(x==se) return nw;
        if(x==sw) return ne;
        if(x==nw) return se;
    }
    int lt(int &x,int &y,int dir)
    {
        if(dir==se) y++;
        if(dir==ne) x--;
        if(dir==sw) x++;
        if(dir==nw) y--;
    }
    int rt(int &x,int &y,int dir)
    {
        if(dir==se) x++;
        if(dir==ne) y++;
        if(dir==sw) y--;
        if(dir==nw) x--;
    }
    int change(pair<int,pair<int,int> > d,int dir,int &x,int &y)
    {
        int a=d.first,b=d.second.first,c=d.second.second;
        if(a)
        {
            if(b&&c) 
            {
                flag=1;
                return ni(dir);
            }
            if((!b)&&c) 
            {
                lt(x,y,dir);
                return left(dir);
            }
            if(b&&(!c)) 
            {
                rt(x,y,dir);
                return right(dir);
            }
            if((!b)&&(!c)) 
            {
                flag=1;
                return ni(dir);
            }
        }
        else 
        {
            x+=xi[dir];y+=yi[dir];
            return dir;
        }
    }
    pair<int,pair<int,int> > gnum(int x,int y,int dir)
    {
        pair<int,pair<int,int> > a;
        if(dir==sw)
        {
            a.first=mp[1LL*(x+1)*tmp+y-1];
            a.second.first=mp[1LL*(x+1)*tmp+y];
            a.second.second=mp[1LL*x*tmp+y-1];
        }
        if(dir==nw)
        {
            a.first=mp[1LL*(x-1)*tmp+y-1];
            a.second.first=mp[1LL*tmp*x+y-1];
            a.second.second=mp[1LL*tmp*(x-1)+y];
        }
        if(dir==ne)
        {
            a.first=mp[1LL*(x-1)*tmp+y+1];
            a.second.first=mp[1LL*(x-1)*tmp+y];
            a.second.second=mp[1LL*x*tmp+y+1];
        }
        if(dir==se)
        {
            a.first=mp[1LL*(x+1)*tmp+y+1];
            a.second.first=mp[1LL*x*tmp+y+1];
            a.second.second=mp[1LL*(x+1)*tmp+y];
        }
        return a;
    }
    pair<int,int> find(int x,int y,int r)
    {
        if(r==ne) 
        {
            int t=lower_bound(rst[x+y].begin(),rst[x+y].end(),x)-rst[x+y].begin()-1;
            t=rst[x+y][t]+1;
            return mr(t,x+y-t);
        }
        if(r==se) 
        {
            int t=lower_bound(man[x-y+m+1].begin(),man[x-y+m+1].end(),x)-man[x-y+m+1].begin();
            t=man[x-y+m+1][t]-1;
            return mr(t,-(x-y-t));
        }
        if(r==sw)
        {
            int t=lower_bound(rst[x+y].begin(),rst[x+y].end(),x)-rst[x+y].begin();
            t=rst[x+y][t]-1;
            return mr(t,x+y-t);
        }
        if(r==nw) 
        {
            int t=lower_bound(man[x-y+m+1].begin(),man[x-y+m+1].end(),x)-man[x-y+m+1].begin()-1;
            t=man[x-y+m+1][t]+1;
            return mr(t,-(x-y-t));
        }
    }
    void work(int x,int y,int dr)
    {
        for(int i=1;i<=4;i++)
            if(dr==i)
            {
                pair<int,int> nxt=find(x,y,i);
                ans+=abs(nxt.first-nx)+1;
                nx=nxt.first;ny=nxt.second;
                return ;
            }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        while(k--)
        {
            scanf("%d%d",&x,&y);
            man[x-y+m+1].push_back(x);
            rst[x+y].push_back(x);
            mp[1LL*x*tmp+y]=1;
        }
        for(int i=1;i<=m;i++) 
        {
            mp[0*tmp+i]=1;mp[1LL*tmp*(n+1)+i]=1;
            man[0-i+m+1].push_back(0);
            rst[0+i].push_back(0);
            man[n+1-i+m+1].push_back(n+1);
            rst[n+i+1].push_back(n+1);
        }
        for(int i=1;i<=n;i++)
        {
            mp[1LL*i*tmp+0]=1;mp[1LL*i*tmp+m+1]=1;
            man[i-0+m+1].push_back(i);
            rst[i+0].push_back(i);
            man[i-m-1+m+1].push_back(i);
            rst[i+m+1].push_back(i);
        }
        mp[0]=1;mp[1LL*tmp*(n+1)+0]=1;mp[1LL*0*tmp+m+1]=1;mp[1LL*tmp*(n+1)+m+1]=1;
        man[0-0+m+1].push_back(0);
        rst[0+0].push_back(0);
        man[n+1-0+m+1].push_back(n+1);
        rst[n+1+0].push_back(n+1);
        man[0-m-1+m+1].push_back(0);
        rst[0+m+1].push_back(0);
        man[n+1-m-1+m+1].push_back(n+1);
        rst[n+1+m+1].push_back(n+1);
        for(int i=0;i<=max(n,m)*2+2;i++) sort(man[i].begin(),man[i].end());
        for(int i=0;i<=max(n,m)*2+2;i++) sort(rst[i].begin(),rst[i].end());
        scanf("%d%d",&sx,&sy);
        scanf("%s",s+1);
        nx=sx;ny=sy;fr=dr=jud();
        work(nx,ny,dr);
        pair<int,pair<int,int> > dd=gnum(nx,ny,dr);
        dr=change(dd,dr,nx,ny);
        sx=nx;sy=ny;fr=dr;
        ans=0;
        do
        {
            work(nx,ny,dr);
            pair<int,pair<int,int> > dd=gnum(nx,ny,dr);
            dr=change(dd,dr,nx,ny);
        }while(!(nx==sx&&ny==sy&&dr==fr));
        printf("%lld
    ",ans>>flag);
        return 0;
    }
    light
  • 相关阅读:
    一个printf(结构体指针)引发的血案
    C语言指针从底层原理到花式技巧,用图文和代码帮你讲解透彻
    利用C语言中的setjmp和longjmp,来实现异常捕获和协程
    提高代码逼格的利器:宏定义从入门到放弃
    我最喜欢的进程之间通信方式消息总线
    推荐一个阅读代码、文档的利器:屏幕贴图工具
    计算机网络基础知识总结
    vi指令总结
    LVS 负载均衡器理论基础及抓包分析
    Linux命令总结大全,包含所有linux命令
  • 原文地址:https://www.cnblogs.com/Lrefrain/p/11228648.html
Copyright © 2020-2023  润新知