• 2016.11.2第57套模拟集训三


    1.神秘大门
    (door.pas/c/cpp)
    【题目描述】
    最近小K大牛经过调查发现,在WZland的最南方——WZ Antarctica 出现了奇怪
    的磁场反应。为了弄清楚这一现象,小K 大牛亲自出马,来到了WZ Antarctica。
    小K大牛发现WZ Antarctica 出现了一道神秘的大门。人总有好奇心,小K大牛想打开
    这扇神秘大门,看门的后面究竟是什么东西,但用尽什么办法也不能打开这扇门。
    突然,门上出现了一些奇怪的字符。凭着敏锐的直觉,小K 认为这些符号就是打
    开这扇门的关键, 于是小K 抓紧时间开始研究这些符号。
    经过一些时间的研究,小K 大牛发现这些符号其实是一串密码,只有破解了
    这个密码, 才能打开那扇神秘大门。这个密码十分简单,他给出了两个很长的字
    符串A 和B,你只需要判断B 是否在A 中出现过就可以了,当然如果B 在A
    中出现,那么你还需要输出B 的字符在A 中依次出现的位置。
    这里解释一下B 在A 中出现的概念,设A=S1S2…SN,B= T1T2…TM,如果存
    在一组数K:K1<K2<…<KM,使得B=SK1SK2…SKM,那么就可以认为B 在A 出现
    过。比如说A=sdfesad, B=sfsad,那么B 在A 中出现过,因为B 中的字符在A
    中依次出现的位置为1 3 5 6 7。
    这个解密过程实在太简单了,于是小K 大牛就将这个任务交给了你。由于小K
    大牛十分着急,他只给了你1s 的时间。
    【输入】
    输入数据包含2 行,分别包含一个字符串,第一行输入的是字符串A,第二
    行输入的是字符串B。

    【输出】
    第一行输出一个字符串“Yes”或“No”,如果B 在A 中出现,那么输出“Yes”,
    否则输出“No”。
    如果你的第一行输出“Yes”,那么在第接下来若干行你需要输出一组数K,使
    得B=SK1SK2…SKM,每行一个数;否则第二行为空。如果存在多组数据满足条件,
    你需要输出字典序最大的一组。
    【输入输出样例1】
    door.in        door.out
    sdfesad       Yes
    sfsad          1
                      3
                      5
                      6
                      7
    【输入输出样例2】
    door.in        door.out
    abcdef         No
    acdefg

    题解:

    第一题啊,简单的我以为我最开始想少了。就是从后往前扫,扫到了就输出return ; o(N)。easy

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MN 10000005
    using namespace std;
    char a[MN],b[MN];
    int pos[MN],lena,lenb;
    void readin()
    {
        cin>>a;
        cin>>b;
        lena=strlen(a);
        lenb=strlen(b);
    }
    void work()
    {
        int j=lenb-1;
        for(int i=lena-1;i>=0;i--)
        if(a[i]==b[j])
        {
            pos[j]=i+1;
            j--;
            if(j==-1) return ;
        }
    }
    void prin()
    {
        if(pos[0]==0) {cout<<"No"<<endl; return ;}
        cout<<"Yes"<<endl;
        for(int i=0;i<lenb;i++) cout<<pos[i]<<endl;
        return ;
    }
    int main()
    {
        freopen("door.in","r",stdin);
        freopen("door.out","w",stdout);
        readin();
        work();
        prin();
        return 0;
    }

    2. 集结蚂蚁
    (ant.c/cpp/pas)
    【题目描述】
    雄心勃勃的企业家达伦·克劳斯发现了皮姆博士有关缩小原子间距离的公式并
    研发出新一代微型“黄蜂战士”,皮姆博士担忧武器会引发不可挽回的后果,于是
    找到斯科特并使他成为了新一代“蚁人”。正逢克劳斯与外商交易黄蜂战衣的那天,
    斯科特受命前往摧毁黄蜂战衣并销毁数据,然而一个人的力量是渺小的,斯科特需
    要走入一个巨大的蚁穴去召唤蚂蚁与他共同作战。
    蚁穴是一个巨大复杂的地带,由n 行m 列组成,每个偶数行存在至少一个蚂蚁
    聚集地,同一行的不同蚂蚁聚集地以一堵墙隔开,每个蚂蚁聚集地的大小为Si;
    每个奇数行存在连接相邻偶数行中蚂蚁聚集地的路径,一个蚂蚁聚集地可能有多条
    路径可以到达。
    蚁人可从蚁穴的第一行任何一路口出发,由于时间紧迫,蚁人只能向下一行走,
    在这种情况下,蚁人希望你能告诉他如何使经过的蚂蚁聚集地大小之和最大,从而
    召唤最多的蚂蚁。
    【输入】
    第1 行包含两个用空格隔开的整数n,m,意义见描述。
    第2 到n+1 行,每行m 个字符(无间隔)且仅存在0 和1:同一偶数行中连
    续x 个0 组成一个大小为x 的蚂蚁聚集地,1 为墙体;奇数行中0 表示蚁人可以从
    此处通过。
    【输出】
    对于每组数据输出一个整数,表示经过路径中最大聚集地之和(不包含聚集
    地之间的路径)。若蚁人无法到达最后一行则请输出“-1”。
    4
    【输入样例】
    10 10
    1111101111
    1100001011
    1101111111
    1100000101
    1110110111
    1000110001
    1101111011
    1101000011
    1101011111
    1101010001
    【输出样例】
    17
    【样例解释】

    1111101111
    1100001011
    1101111111
    1100000101
    1110110111
    1000110001
    1101111011
    1101000011
    1101011111
    1101010001
    【数据规模】
    对于20%的数据,n≤20,m≤20
    对于50%的数据,n≤20,m≤100
    对于100%的数据,n≤5000,m≤2000,保证n 是一个偶数,路径的数量不多于1×106

    一开始想要建图,但是当时以为会超时,毕竟路径都有106那么多。然后大神告诉我们并不会超时,而且数据更大的时候只能建图了。见图可以不管重边,管了的话,反而要超时,索性不理。建完图后,拓扑排序加dp。我个人用的是递推,嗨呀,就是直接dp了,然而当时没有注意中间短路的情况,GG了10分。后来改了就对了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MN 5005
    #define MM 2005
    using namespace std;
    int n,m,mapp[MN][MM],f[MM],ans;
    void inint()//just need dp like in the tree
    {
    	bool flag;
    	for(int i=n;i>=1;i--)
    	{
    		flag=false;
    		for(int j=1;j<=m;j++)
    		{
    			if(mapp[i][j]==0&&i%2==0)//the qiang is meaningless
    			{
    				int len=0,ma=-100;
    				while(j+len<=m&&mapp[i][j+len]==0)
    				{if(f[j+len]>ma) 
    				ma=f[j+len];
    				len++;}
    				if(ma!=-1)
    				for(int k=j;k<len+j;k++) f[k]=len+ma;
    				j+=len;
    			}
                if(mapp[i][j]==1) f[j]=-1;
    		}
    		for(int j=1;j<=m;j++)
    		if(f[j]) flag=true;
    	    if(flag==false) 
    		{
    			ans=-1; 
    			return ;
    		}
    	}
    		
    }
    
    int main()
    {
    	freopen("ant.in","r",stdin);
    	freopen("ant.out","w",stdout);
    	cin>>n>>m;
    	for(int i=1;i<=n;i++)
    	{
    		getchar();
    		for(int j=1;j<=m;j++)
    		mapp[i][j]=getchar()-'0';
    	}
    		
        inint();
    	for(int i=1;i<=m;i++)
    	if(f[i]>ans) ans=f[i];
    	if(ans==0) ans=-1;
    	cout<<ans<<endl;
    	return 0;
    }

    3. 计数
    (amount. pas/c/cpp)
    【题目描述】
    我们都爱奎奎,最近奎奎给大家出了一道题。
    他告诉了我们一个n*m 的矩阵点,在这个矩阵中的点可以连接成很多线,求
    长度等于某一长度的线的条数。
    【输入】)
    第一行三个正整数n,m,t,第2-t+1 行为所求Wi。
    【输出】
    输出1 行,共t 个数,第i 个数为满足长度Wi 的条数。
    【输入样例1】
    3 3 1 例如此为3*3 的矩阵点
    1
    【输出样例1】
    12
    【输入样例2】
    7 11 1
    5
    【输出样例2】
    168
    【输入样例3】
    3 5 1
    2
    【输出样例3】
    14
    【数据说明】
    测试点数据范围
    1 2 N<=2000;M<=2000;T<=100
    3 4 N<=1000000;M<=1000000;T<=100
    5 6 N<=10000000;M<=10000000;T<=100
    7 8 N<=100000000;M<=100000000;T<=100
    9 10 N<=1000000000;M<=1000000000;T<=100
    W<=2max(n,m);

    题解:GG,考试的时候没有想出来正解,暴力还错了,因为没有注意到输出居然是一行!因为这道题算的是两个任意点之间的距离等于所求的距离。那么我们可以分为两个部分,一些是在坐标线上的,一些是不在坐标线上但是可以由勾股定理求得。前者很简单,simple这里就不说了。关键是后者枚举勾股数,而且我们晓得这个n和m都很大,直接枚举绝对GG。然后我是没有想出来的,嗨呀,太垃圾了。后来看题解,在那里推了半天,最后写出来还是GG,再一看,d与2*r/d弄混了。嗨呀,气。先把题解复制过来,红色是题解不清楚的地方:

    因为x^2+y^2=r^2;

    y=sqrt(r^2-x^2);

    y=sqrt((r-x)*(r+x));

    令d=gcd(r+x,r-x);

    设A=(r-x)/d,B=(r+x)/d;

    必然存在gcd(A,B)=1;

    y^2=d^2*A*B;

    A*B是完全平方数;

    所以A是完全平方数,B是完全平方数;

    设A=a*a,B=b*b;

    显然a!=b;

    令a<b;

    所以a*a=(r-x)/d;

    b*b=(r+x)/d;

    两式相加得a*a+b*b=2r/d;所以说本来要枚举d从1-2r的,此处只用枚举到根号2r,来优化这个时间

    1<d<sqrt(2r);

    枚举d;

     此时d为2R的约数有两种情况:d=d或d=2R/d。这个地方千万不要弄混了,左边的d一直代表的是上面a*a+b*b=2r/d中的d=2r/d时,只不过是枚举另一个2r的因子,代入的时候还是带分母,不然就GG

             第一种情况:d=2r/d。枚举a∈[1,sqrt(2R/2d)] <由2*a*a < 2*r/d转变来>,算出对应的b=sqrt(2r/d-a^2),检查是否此时的A,B满足:A≠B且A,B互质 

             第二种情况:d=d。枚举a∈[1,sqrt(d/2)] <由2*a*a < d转变来>,算出对应的b=sqrt(d-a^2),检查是否此时的A,B满足:A≠B且A,B互质 

    可以轻松求出x^2+y^2=r^2得整数解;

    然后O(1)查询当前解的个数;

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #define ll long long
     6 using namespace std;
     7 int n,m,t;
     8 ll w;
     9 ll gcd_(ll x,ll y)
    10 {
    11     if(y==0) return x;
    12     return gcd_(y,x%y);
    13 }
    14 void findnum(ll x)//double?
    15 {
    16     ll tims=0,nowt;
    17     ll wid=0,hig=0;
    18     if(x<=n) tims+=(n-x)*m;
    19     if(x<=m) tims+=(m-x)*n;     
    20     for(ll d=1;d*d<=2*x;d++)
    21     if((2*x)%d==0)
    22     {
    23         for(ll a=1;a*a*2<=d;a++)
    24         {
    25             ll b=floor(sqrt(d-a*a));
    26             if(b*b+a*a<d) continue ;
    27             if(a==b) continue ;
    28             if(gcd_(a,b)!=1) continue ;
    29             wid=(b*b-a*a)*(2*x/d)/2,hig=(2*x/d)*a*b;
    30             if(wid>=hig) continue ;
    31             if(n>=wid&&m>=hig)
    32             {
    33             nowt=(n-wid)*(m-hig)*2;//from 1/4 part so it's twice
    34             tims+=nowt;
    35             }
    36             if(n>=hig&&m>=wid)
    37             {
    38             swap(hig,wid);
    39             nowt=(n-wid)*(m-hig)*2;
    40             tims+=nowt;
    41             }
    42         }
    43         for(ll a=1;a*a*d<=x;a++)
    44         {
    45             ll b=floor(sqrt(2*x/d-a*a));
    46             if(b*b+a*a<(2*x/d)) continue ;
    47             if(a==b) continue ;
    48             if(gcd_(a,b)!=1) continue ;
    49             wid=(b*b-a*a)*d/2,hig=d*a*b;
    50             if(wid>=hig) continue ;
    51             if(n>=wid&&m>=hig)
    52             {
    53             nowt=(n-wid)*(m-hig)*2;//from 1/4 part so it's twice
    54             tims+=nowt;
    55             }
    56             if(n>=hig&&m>=wid)
    57             {
    58             swap(hig,wid);
    59             nowt=(n-wid)*(m-hig)*2;
    60             tims+=nowt;
    61             }
    62         }
    63     }
    64     cout<<tims<<' ';
    65 }
    66 int main()
    67 {
    68     freopen("amount.in","r",stdin);
    69     freopen("amount.out","w",stdout);
    70     cin>>n>>m>>t;
    71     while(t)
    72     {
    73         cin>>w;
    74         findnum(w);
    75         t--;
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    ProtoType Design Tools
    什么是publickeytoken及publickeytoken的作用
    Windows最高权限system帐户
    Q70 AV01本本安装MAC
    解决MDict3在PPC下乱码的问题
    QT_XSP.CPP
    QT_XSP.CPP
    SetupFactory脚本
    DVD IFO FILE HEADER
    SerialPort comstat is being used without defining
  • 原文地址:https://www.cnblogs.com/fisch/p/6024375.html
Copyright © 2020-2023  润新知