zoukankan      html  css  js  c++  java
  • 7.22 NOIP模拟7

    又是炸掉的一次考试

    T1.方程的解

      本次考试最容易骗分的一道题,但是由于T2花的时间太多,我竟然连a+b=c都没判。。暴力掉了40分。

      首先a+b=c,只有一组解。

      然后是a=1,b=1,答案是c-1,不解释。

      对于最大的数据,我们可以用exgcd求出一组特解,之后的通解为x+(b/gcd)*k, y+(a/gcd)*k.

      求出正整数解的个数即可。

      注意有很多特判,慢慢调试就好(改这题的时间比我改T3的时间都长)

    #include<bits/stdc++.h>
    #define m 65535
    #define int long long
    using namespace std;
    int t,a,b,c,x,y;
    long long ans;
    int exgcd(int a,int b,int &x,int &y)
    {
        if(b==0)
        {
            x=1,y=0;
            return a;
        }
        int gcd=exgcd(b,a%b,y,x);
        y-=(a/b)*x;
        return gcd;
    }
    main()
    {
        scanf("%lld",&t);
        while(t--)
        {
            ans=0;
            scanf("%lld%lld%lld",&a,&b,&c);
            if(a+b==c&&a>=1&&b>=1)
            {
                puts("1");
                continue;
            }
            if(a<0&&b<0&&c<0)
                a=-a,b=-b,c=-c;
            if(a==1&&b==1)
            {
                ans=c-1;
                if(ans>0&&ans<=65535)
                {
                    printf("%lld
    ",ans);
                    continue;
                }
                if(ans<=0)
                    puts("0");
                if(ans>m)
                    puts("ZenMeZheMeDuo");
                continue;
            }
            if(t<=100&&a<=1000&&a>=1&&b<=1000&&b>=1&&c>=1&&c<=1000)
            {
                for(int i=1;i<=1000;i++)
                    for(int j=1;j<=1000;j++)
                    {
                        if(a*i+b*j>c)break;
                        if(a*i+b*j==c)ans++;
                    }
                if(ans>m)puts("ZenMeZheMeDuo");
                else printf("%lld
    ",ans);
                continue;
            }
            if(a==0&&b==0)
            {
                if(c==0)puts("ZenMeZheMeDuo");
                else puts("0");
                continue;
            }
            if(a==0)
            {
                if(b>0)
                {
                    if(c>0&&(!(c%b)))puts("ZenMeZheMeDuo");
                    else puts("0");
                }
                if(b<0)
                {
                    if(c<0&&(!(c%b)))puts("ZenMeZheMeDuo");
                    else puts("0");
                }
                continue;
            }
            if(b==0)
            {
                if(a>0)
                {
                    if(c>0&&(!(c%a)))puts("ZenMeZheMeDuo");
                    else puts("0");
                }
                if(a<0)
                {
                    if(c<0&&(!(c%a)))puts("ZenMeZheMeDuo");
                    else puts("0");
                }
                continue;
            }
            if((a<0&&b<0&&c>=0)||(a>0&&b>0&&c<=0))
            {
                puts("0");
                continue;
            }
            if(a<0&&b<0&&c<0)
                a=-a,b=-b,c=-c;
            int gcd=exgcd(a,b,x,y);
            if(c%gcd)
            {
                puts("0");
                continue;
            }
            if(a*b<0)
            {
                puts("ZenMeZheMeDuo");
                continue;
            }
            int k=c/gcd,xx=b/gcd,yy=a/gcd;
            x*=k,y*=k;
            if(xx<0)
                xx=-xx,yy=-yy;
            if(x<=0)
            {
                int xxx=x/xx+1;
                x+=xxx*xx,y-=yy*xxx;
            }
            if(y<=0)
            {
                int xxx=y/yy+1;
                x-=xx*xxx,y+=yy*xxx;
            }
            while(x<=0)
                x+=xx,y-=yy;
            while(y<=0)
                x-=xx,y+=yy;
            if(!x||!y)
            {
                puts("0");
                continue;
            }
            if(x/y<0||y/x<0)
            {
                puts("0");
                continue;
            }
            int aa=x/xx+1,bb=y/yy+1;
            if(!(x%xx))aa--;
            if(!(y%yy))bb--;
            ans=max(aa,bb);
            if(ans>m)puts("ZenMeZheMeDuo");
            else printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    T2.visit

      本场考试最可惜的一道题,打出正解,却因为答案为0的特判wa(改一个字符,70分->AC)

      考试的时候先打了个n^3dp,然后开始找规律

      10,5,5 = C(10,5)*C(10,0);    
      10,4,4 = C(10,5)*C(10,1);    10,4,6=C(10,4)*C(10,0);
      10,3,3 = C(10,5)*C(10,2);    10,3,5=C(10,4)*C(10,1);        10,3,7=C(10,3)*C(10,0);
      10,2,2 = C(10,5)*C(10,3);    10,2,4=C(10,4)*C(10,2);        10,2,6=C(10,3)*C(10,1);        10,2,8=C(10,2)*C(10,0);
      10,1,1 = C(10,5)*C(10,4);
      10,0,0 = C(10,5)*C(10,5);

      这个表我没有打完,但是我感觉已经很显然了,ans=C(t,(t-n-m)/2)*C(t,(t-n+m)/2);(n>m)

       注意特判无解情况,t-n-m为奇数时,必然无解。

       然后我终于理解了数据范围最后,mod为若干质数乘积的意思。。。

      恩,然后我就开始手推crt,码码码,大概一个小时调完了,和dp对了几个点,感觉没啥问题,没打对拍放心的去看T3了。

      考后发现自己打了个这个:

      

    if(((t%(n+m))&1))
        {
            puts("0");
            return 0;
        }

      ???????????我干了啥?把%改成-,AC。一个特判卡掉30分,我。。。。

      至于组合数的解释,请参考其他人的题解。(其实是我不会解释

     1 #include<cstdio>
     2 #include<cmath>
     3 using namespace std;
     4 inline int read(){
     5     register int ss=0;register char bb=getchar();
     6     while(bb<48||bb>57)bb=getchar();
     7     while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
     8     return ss;    
     9 }
    10 inline long long power(long long x,int y,int const mod){
    11     long long ans=0;
    12     for(;y;y>>=1,x=(x<<1)%mod)
    13         if(y&1)ans=(ans+x)%mod;
    14     return ans;
    15 }
    16 int const t=read(),p=read();
    17 int n,m,tot;
    18 long long prime[15],f[15],invv[15];
    19 inline void split(long long x,int lit){
    20     for(register int i=2;i<=lit && x^1;++i)
    21         if(!(x%i))prime[++tot]=i,x/=i;
    22     if(x^1)prime[++tot]=x;
    23     return ;
    24 }
    25 long long exgcd(long long a,long long b,long long &x,long long &y){
    26     if(!b)return x=1,y=0,1;
    27     long long z=exgcd(b,a%b,x,y),lh=x;
    28     x=y,y=lh-a/b*y;
    29     return z;
    30 }
    31 inline long long inv(long long x,long long mod){
    32     long long a,b,c=exgcd(x,mod,a,b);
    33     if(c^1)return -1;
    34     if(a<0)a=a%mod+mod;
    35     return a;
    36 }
    37 inline long long cp(long long x,long long y,long long const mod){
    38     if(x<y)return 0;
    39     if(!y || x==y)return 1;
    40     if(y>x-y)y=x-y;
    41     long long a=1,b=1;
    42     for(register int i=0;i<y;++i)
    43         a=a*(x-i)%mod,b=b*(y-i)%mod;
    44     return a*inv(b,mod)%mod;
    45 }
    46 long long lucas(long long x,long long y,long long  mod){
    47     if(x<y)return 0;
    48     if(x==y)return 1;
    49     return y?cp(x%mod,y%mod,mod)*lucas(x/mod,y/mod,mod)%mod:1;
    50 }
    51 inline long long china(){
    52     long long ans=0;
    53     for(register int i=1;i<=tot;++i)
    54         ans=(ans+power(p/prime[i],power(invv[i],f[i],p),p))%p;
    55     return ans;
    56 }
    57 inline long long cq(int x,int y){
    58     for(register int i=1;i<=tot;++i)
    59         f[i]=lucas(x,y,prime[i]);
    60     return china();
    61 }
    62 inline void swap(int &x,int &y){
    63     int z=x;
    64     x=y,y=z;
    65     return ;
    66 }
    67 signed main(){
    68     n=read(),m=read();
    69     if(n<m)swap(n,m);
    70     split(p,sqrt(p));
    71     for(register int i=1;i<=tot;++i)
    72         invv[i]=inv(p/prime[i],prime[i]);
    73     printf("%lld",cq(t,t-n+m>>1)*cq(t,t-n-m>>1)%p);
    74     return 0;
    75 }
    这是remarkable的代码

    T3.光

      没想到一道模拟题卡掉了我50分。。。暴力都打错了,骗到20分,考完后发现加clock等一大堆特判可以卡到80分。

      正解就是模拟,但是优化了一下。首先,在原来的基础上,可以直接考虑到当前状态的终点:二分。

      在同一种状态中,横纵坐标之和或差必然不变,因此我们可以将黑块存进保存坐标之和或差的vector中,给每个vector排序后二分。

      但是我们似乎忽略了一个问题:如何统计答案?

      一个非常简单却不好想的结论:若一个块被经过,则光线必然只穿过他的一条对角线。

      证明如下:

      我们给每两个相邻的方块染上不同的颜色,则同一种状态的光线只经过同种颜色的方块。而除了反向反射的两种状态,另外两种反射方式必然从一种颜色的方块变成另一种,即,经过右下->左上对角线和右上->左下对角线的光线穿过的方块颜色必不相同,所以同一方块不可能被穿过两条对角线。

      既然如此,那么就又有一个非常显然的结论:一个方块最多被经过两次,两次穿过同一对角线且方向相反。

      那么一个方块被经过两次的条件呢?当且仅当发生了反向的反射。同样,若发生了反向的反射,反向光线会将原光线的所有路径重走一遍,因此,一旦发生反向反射,所有被经历的方块都会被穿过两次。否则,每个方块仅被穿过一次。

      因此,我们可以记录是否发生了反向的反射,若发生了,最后统计的答案数/2。计算每种状态的贡献时,只需将起始节点和终点的横(纵)坐标相减即可。

      注意反射情况十分复杂,分类讨论即可。为了方便,多调几个STL挺好的。

      1 #include<bits/stdc++.h>
      2 #define mk(a,b,c) mp(a,mp(b,c))
      3 #define mp(a,b) make_pair(a,b)
      4 #define pb push_back
      5 using namespace std;
      6 int n,m,k;
      7 long long ans=0;
      8 bool v;
      9 vector<int>h[200005],g[200005];
     10 map<pair<int,pair<int,int> >,bool>c;
     11 map<pair<int,int>,bool>kk;
     12 int main()
     13 {
     14     scanf("%d%d%d",&n,&m,&k);int kkk=max(n,m);
     15     for(int i=1;i<=k;i++)
     16     {
     17         int x,y;
     18         scanf("%d%d",&x,&y);
     19         kk[mp(x,y)]=true;
     20         h[x+y].pb(x-y);
     21         g[x-y+kkk].pb(x+y);
     22     }
     23     for(int i=0,x,y;i<=m+1;i++)
     24     {
     25         x=0,y=i;
     26         kk[mp(x,y)]=true;
     27         h[x+y].pb(x-y);
     28         g[x-y+kkk].pb(x+y);
     29         x=n+1;
     30         kk[mp(x,y)]=true;
     31         h[x+y].pb(x-y);
     32         g[x-y+kkk].pb(x+y);
     33     }
     34     for(int i=0,x,y;i<=n+1;i++)
     35     {
     36         x=i,y=0;
     37         kk[mp(x,y)]=true;
     38         h[x+y].pb(x-y);
     39         g[x-y+kkk].pb(x+y);
     40         y=m+1;
     41         kk[mp(x,y)]=true;
     42         h[x+y].pb(x-y);
     43         g[x-y+kkk].pb(x+y);
     44     }
     45     for(int i=0;i<=kkk+kkk+2;i++)
     46         sort(h[i].begin(),h[i].end()),
     47         sort(g[i].begin(),g[i].end());
     48     int x,y,zt,i=0;
     49     string ss;
     50     cin>>x>>y>>ss;
     51     if(ss=="NE")zt=0;
     52     if(ss=="NW")zt=1;
     53     if(ss=="SE")zt=2;
     54     if(ss=="SW")zt=3;
     55     while(!c[mk(x,y,zt)])
     56     {
     57         c[mk(x,y,zt)]=true;i++;
     58         if(zt==0)
     59         {
     60             int cc=*--upper_bound(h[x+y].begin(),h[x+y].end(),x-y),
     61                 xx=(x+y+cc)>>1,yy=(x+y-cc)>>1;
     62             if(i^1)ans+=abs(x-xx);
     63             if((kk[mp(xx+1,yy)]&&kk[mp(xx,yy-1)])
     64             ||(!kk[mp(xx+1,yy)]&&!kk[mp(xx,yy-1)]))
     65             {
     66                 zt=3,x=xx+1,y=yy-1;
     67                 if(i^1)v=true;
     68             }
     69             else if(kk[mp(xx+1,yy)])
     70                 zt=1,x=xx,y=yy-1;
     71             else if(kk[mp(xx,yy-1)])
     72                 zt=2,x=xx+1,y=yy;
     73         }
     74         else if(zt==3)
     75         {
     76             int cc=*upper_bound(h[x+y].begin(),h[x+y].end(),x-y),
     77                 xx=(x+y+cc)>>1,yy=(x+y-cc)>>1;
     78             if(i^1)ans+=abs(x-xx);
     79             if((kk[mp(xx-1,yy)]&&kk[mp(xx,yy+1)])
     80             ||(!kk[mp(xx-1,yy)]&&!kk[mp(xx,yy+1)]))
     81             {
     82                 zt=0,x=xx-1,y=yy+1;
     83                 if(i^1)v=true;
     84             }
     85             else if(kk[mp(xx-1,yy)])
     86                 zt=2,x=xx,y=yy+1;
     87             else if(kk[mp(xx,yy+1)])
     88                 zt=1,x=xx-1,y=yy;
     89         }
     90         else if(zt==1)
     91         {
     92             int cc=*--upper_bound(g[x-y+kkk].begin(),g[x-y+kkk].end(),x+y),
     93                 xx=(x-y+cc)>>1,yy=(cc-x+y)>>1;
     94             if(i^1)ans+=abs(x-xx);
     95             if((kk[mp(xx+1,yy)]&&kk[mp(xx,yy+1)])
     96             ||(!kk[mp(xx+1,yy)]&&!kk[mp(xx,yy+1)]))
     97             {
     98                 zt=2,x=xx+1,y=yy+1;
     99                 if(i^1)v=true;
    100             }
    101             else if(kk[mp(xx+1,yy)])
    102                 zt=0,x=xx,y=yy+1;
    103             else if(kk[mp(xx,yy+1)])
    104                 zt=3,x=xx+1,y=yy;
    105         }
    106         else if(zt==2)
    107         {
    108             int cc=*upper_bound(g[x-y+kkk].begin(),g[x-y+kkk].end(),x+y),
    109                 xx=(x-y+cc)>>1,yy=(cc-x+y)>>1;
    110             if(i^1)ans+=abs(x-xx);
    111             if((kk[mp(xx-1,yy)]&&kk[mp(xx,yy-1)])
    112             ||(!kk[mp(xx-1,yy)]&&!kk[mp(xx,yy-1)]))
    113             {
    114                 zt=1,x=xx-1,y=yy-1;
    115                 if(i^1)v=true;
    116             }
    117             else if(kk[mp(xx+1,yy)])
    118                 zt=3,x=xx,y=yy-1;
    119             else if(kk[mp(xx,yy+1)])
    120                 zt=0,x=xx-1,y=yy;
    121         }
    122     }
    123     printf("%lld
    ",v?ans/2:ans);
    124     return 0;
    125 }
    大模拟
  • 相关阅读:
    Demo源码放送:打通B/S与C/S !让HTML5 WebSocket与.NET Socket公用同一个服务端!
    WebSocket 网页聊天室的实现(服务器端:.net + windows服务,前端:Html5)
    数据科学求职准备
    c#使用MethodInvoker解决跨线程访问控件
    zedboard--Opencv移植和zedboard测试(十一)
    浅谈C++调用C#的DLL程序方法
    linux内核--进程空间(二)
    Windows 下如何安装配置Snort视频教程
    十分钟搭建自己的hadoop2/CDH4集群
    MFC调用c#的dll
  • 原文地址:https://www.cnblogs.com/hzoi-cbx/p/11228437.html
Copyright © 2011-2022 走看看