「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\n",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\n",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\n",ans>>flag);
    return 0;
}
light

 

转载于:https://www.cnblogs.com/Lrefrain/p/11228648.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值