2012-01-20 ACM群群赛

1005题

codeforces上某题的加强版,我也是弄了好久才ac的,代码比较暴力,m,length都不是很大 100*11000*10(可能写错了),1s内还是ac了。


其中字符串的左移问题,我是把s串加倍,变成s+s然后再对s+s进行一个for循环预处理,判定的时候注意长度小于和等于length_s,还注意起点。。。见代码。。。

/*2012-01-20 20:42:38	Accepted	1005	671 MS	1132 KB	GNU C++*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a));
typedef unsigned long long u64;
typedef long long lld;
#define maxn 20000

char ch[maxn], temp[ maxn+maxn ];
struct Info{
    int len,kind;
    char c[200];
}node[200];

int ans[maxn];

int next[maxn][26];
int solve(char *s,char *t){
    int i,j,ns,nt;
    ns= strlen(s);
    nt= strlen(t);
    for(i=0;i<26;++i)
        next[ns-1][i]= -1;
    for(i=ns-2;i>=0;--i){
        for(j=0;j<26;++j)
            next[i][j]= next[i+1][j];
        next[i][ s[i+1]-'a' ]= i+1;
    }

    int index;
    if( s[0]==t[0] ) index= 0;
    else index= next[0][t[0]-'a'];

    i= index;
    int n= (ns>>1);
    while(index<= n && index!=-1 ){
        i= index;
        for(j=1;j<nt;++j){
            int NEXT= next[i][ t[j]-'a' ];
            if( NEXT!=-1 && (NEXT-index+1)<= n )
                i= NEXT;
            else break;
        }
        if( j>=nt ) return 1;
        else index= next[index][t[0]-'a'];
    }
    return 0;
}

int main()
{
    //freopen("1005.txt","r",stdin);
    int T,m,i,j;
    cin>>T;
    while(T--){
        scanf("%s",ch);
        cin>>m;
        for(i=1;i<=m;++i){
            scanf("%d%s",&node[i].kind,node[i].c);
            node[i].len= strlen( node[i].c );
        }

        for(i=1;i<=m;++i){
            if( node[i].kind==1 )
                strcat( ch, node[i].c );
        }
        //puts(ch);

        int Q=0;
        for(i=m;i>=1;--i){
            if( node[i].kind==1 ){
                int n= strlen( ch );
                ch[ n-node[i].len ]= '\0';
            }
            else{
                strcpy( temp, ch );
                strcat( temp, ch );
                ans[++Q]= solve( temp, node[i].c );
            }
        }

        for(i=Q;i>0;--i)
            if( ans[i]==0 ) puts("NO");
            else puts("YES");
    }
}



1010题

给定n(1<=n<=10^9),求3个实数,使得x+y+z= n,同时使 x* ( y+ z^2 )最大,如果邮多个测试示例,按字典序输出,保留3位小数。


昨晚我的做法是n>=3时, 我瞎蒙的y=0有最大值,然后 f (x)= x* ( (n-x)^2 ),求导之后发现x=n/3,于是写了代码,提交wa,今天问了浮云牛,它的代码思路和我的一样,而不同的是n>=2的时候用这个公式,而我写的是 n=2的时候输出1.000 0.000 1.000

xtu黑水浮云2012-01-21 15:17:59
if(n==1) printf("0.500 0.500 0.000\n");
else printf("%.3f 0.000 %.3f\n",(double)n/3.0,(double)n*2/3.0);

然后群里提出了一个不是求导的方式来理解:

y=0时, x+z =n,有 2*x + z + z = 2*n, 对于 x*(z^2) <==> 0.5*( 2*x * z * z ),3个数的和一定,仅当3个数都相等时乘积最大。

有2x=z, x= n/3(注意C语言里的除法)。


可是,达尔戈提出了另一个观点,应该分x=0,y=0,z=0,3个情况来写, 理由是 对x来说是一次函数,对y来说是一次函数,对z来说是二次函数,一次函数是没有最大值,只能取边界值。


后来又  hnu的晴天大神说了哥拉格朗日乘数法计算,小学了下,发现自己还是不会,请教达尔戈,居然回复不可以用,大致内容如下,看来我果断得看书去:

达尔 2012-01-21 21:48:10
木有极大值
轨迹 2012-01-21 21:48:55
好吧,我理论知识极度匮乏,出题人也忽略了 他说他用了 拉格朗日乘数法来做数据。
达尔 2012-01-21 21:49:25
是的。。。
达尔 2012-01-21 21:49:36
昨晚他们找我就是说这个
轨迹 2012-01-21 21:50:58
最后一个问题,你怎么知道它木有极大值
达尔 2012-01-21 21:53:10
还是下午那个说话。。。你见过一次函数有极大值么
轨迹 2012-01-21 21:53:31
可是 z是二次的 你自己说的。
轨迹 2012-01-21 21:54:05
一个函数的阶次应该是由有次数最高的那个来决定的不是吗
达尔 2012-01-21 21:55:27
拉格朗日乘子法,需要用二次偏导验算,而对x和y的二次偏导都是等于0
达尔 2012-01-21 21:55:36
这是最理论的说法了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值