The 12th Zhejiang University Programming Contest

The 12th Zhejiang University Programming Contest 第十二届浙大校赛题,在zoj上是:3591-3599

这套题可以说是比较难的,真想做7个!!!但是,遗憾的是,这套题真的很难!即使看着集体报告做,我也没做到7个题,而且还有好几个不明白怎么证明,真心给做出来的人跪了。囧……


同样,给一个解题报告网址:http://blog.sina.com.cn/s/blog_5123df350100zk1d.html 


zoj 3591 Nim 这个就是nim的变形,列出给定的a数组,b[i]为前i个数的异或值,则看b[i]中不相同两个数构成的对的个数就是了,当然还要加上单个不为零的情况。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int a[100010], b[100010];

void deal(int N ,int S,int W)
{
    int g = S;
    for (int i=0; i<N; i++) {
        a[i] = g;
        if( a[i] == 0 ) { a[i] = g = W; }
        if( g%2 == 0 ) { g = (g>>1); }
        else           { g = (g>>1) ^ W; }

        if(i != 0) a[i] = a[i]^a[i-1];
    }
}

int main()
{
    int t;
    cin >> t;
    int n,s,w;
    while(t--)
    {
        cin >> n >> s >> w;
        deal(n,s,w);

        memset(b,0,sizeof(0));
        sort(a,a+n);
        int kk = 1;
        b[0] = 1;
        for(int i = 1;i < n;i++)
        {
            if(a[i] != a[i-1])
            {
                b[kk] = 1;a[kk++] = a[i];
            }
            else b[kk-1]++;
        }
        long long re = 0;
        //for(int i = 0;i < kk;i++) cout << a[i] << " " << b[i] << "\n";
        for(int i = 0;i < kk;i++)
            re += (long long)(n - b[i]) * b[i];

        re = re/2;
        re += n;
        if(a[0] == 0) re -= b[0];

        cout << re << "\n";
    }
    return 0;
}

zoj 3592 Flipping the Board 整套题中最难得一个,不会!

zoj 3593 One Person Game 数学题
这个中的A,B太大了,不可能是搜索之类的,只能是数学了,当然是gcd,扩展欧几里得之类的,求出来通解容易,再准确的给出结果却是不简单的,这类题,我最愁的也就是给出结果的部分,

求出通解公式fx,fy之后,当fx,fy异号的时候re= abs(fx)+abs(fy) 当两个同号的时候 re = min(abs(fx),abs(fy));

其实通解是fx=x0+b0t;fy=y0-a0t;  这儿的t 的取值是很有讲究的,大约在fx=0或者fy=0或者fx=fy这三种情况 分别判断就是了

这个是我看了别人的题解之后我才想明白,囧

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
    if(b==0)return a;
    else return gcd(b,a%b);
}
ll ext_gcd(ll a,ll b,ll& x,ll& y)
{
    ll t,ret;
    if (!b)
    {
        x=1,y=0;
        return a;
    }
    ret=ext_gcd(b,a%b,x,y);
    t=x,x=y,y=t-a/b*y;
    return ret;
}
ll get(ll &re,ll xx,ll yy)
{
    if(xx*yy>=0)re=min(re,max(abs(xx),abs(yy)));
    else re=min(re,abs(xx)+abs(yy));
    return re;
}

ll deal(ll &re,ll x,ll y,ll addx,ll addy)
{
    get(re,x,y);
    get(re,x+addx,y-addy);
    get(re,x-addx,y+addy);
    return re;
}
ll get_step(ll x,ll y,ll addx,ll addy)
{
    ll r = (long long)0x7fffffff*10000000,k,kx,ky;
    k=(y-x)/(addx+addy);
    deal(r,x+k*addx,y-k*addy,addx,addy);

    kx=x/addx;
    ky=y/addy;
    deal(r,x+kx*addx,y-kx*addy,addx,addy);
    deal(r,x+ky*addx,y-ky*addy,addx,addy);
    return r;
}
int main()
{
    ll A,B,a,b,t,d,x,y;
    cin>>t;
    while(t--)
    {
        cin>>A>>B>>a>>b;
        A=B-A;
        if(!A)printf("0\n");
        else
        {
            d=gcd(a,b);
            if(A%d) printf("-1\n");
            else
            {
                A/=d;
                a/=d;
                b/=d;
                ext_gcd(a,b,x,y);
                x=x*A;
                y=y*A;
                cout<<get_step(x,y,b,a)<<endl;
            }
        }
    }
    return 0;
}
zoj 3594 给出公元多少年,给出甲子表示,题目挺简单,但是有一个坑,公元纪年没有公元0年直说,公元前1年之后是公元1年!!!!长知识了!

zoj 3595 Two Sequences  高数题,真心的跪了,大一学的东西全部忘干净了,什么无穷级数,什么微分方程,什么求导数,而且有比较复杂的公式变换,囧,就这样吧,结果很简单

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
double a0,x;
int N;
int main()
{
    while(scanf("%lf",&a0)!=EOF)
    {
        scanf("%d",&N);
        double s=0.0;
        for(int i=0;i<N;i++)
        {
            scanf("%lf",&x);
            s+=x*x/2.0+x;
        }s/=(double)N;
        printf("%.8f\n",a0*exp(s));
    }
    return 0;
}

zoj 3596 Digit Number 这个题也是比较难得,但是看解题报告这个是广搜,记忆化的广搜,奇了!!看懂了思路,但是思路还是很模糊,这个都能想出来,看来我的水平还得继续提升啊!!

zoj 3597 Hit the Target! 线段树!!!

线段树可以说做的也不少了,这个难度的还真是不多!可以说这个题的模型难建!现在才知道,自己和大神的差距是多大了,是不是这样的题大神们可以秒杀呢??

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 50010
//Ï߶ÎÊ÷/
int lazy[N*4],num[N*4];
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

void PushUp(int rt)
{
    num[rt] = max(num[rt<<1],num[rt<<1|1]);
}
void PushDown(int rt,int m)
{
    if(lazy[rt])
    {
        lazy[rt<<1] += lazy[rt];
        lazy[rt<<1|1] += lazy[rt];

        num[rt<<1] += lazy[rt];
        num[rt<<1|1] += lazy[rt];
        lazy[rt] = 0;
    }
}
void init(int n)
{
    for(int i = 0;i <= n*4+1;i++)
    {
        lazy[i] = 0;
        num[i] = 0;
    }
}
void update(int L,int R,int c,int l,int r,int rt)
{
    if(R - L < 0) return;
    if(L <= l && r <= R)
    {
        lazy[rt] += c;
        num[rt] += c;
        return;
    }
    PushDown(rt,r-l+1);
    int m = (l+r)>>1;
    if(L <= m) update(L,R,c,lson);
    if(m < R) update(L,R,c,rson);
    PushUp(rt);
}
//

int shot[N];

#define M 100010
struct note
{
    int a,b;
}data[M];
bool cmp(const note a,const note b)
{
    return a.a < b.a || (a.a == b.a && a.b < b.b);
}
int n,m,p,q,k;
void deal(int i,int c)
{
    if(shot[i])
    {
        int t = shot[i];
        int pre = data[t].b-1;
        do
        {
            update(max(pre+1,data[t].b),min(m,data[t].b+q-1),c,1,m,1);
            pre = data[t].b+q-1;
            t++;
        }while(t <= k && data[t].a == data[t-1].a);
    }
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        scanf("%d%d%d%d",&n,&m,&p,&q);
        scanf("%d",&k);
        memset(shot,0,sizeof(shot));

        for(int i = 1;i <= k;i++) scanf("%d%d",&data[i].a,&data[i].b);

        if(k == 0) {cout << "0.00\n";continue;}

        sort(data+1,data+k+1,cmp);

        shot[data[1].a] = 1;
        for(int i = 2;i <= k;i++)
            if(data[i].a != data[i-1].a) shot[data[i].a] = i;

        init(m);//
        for(int i = 1;i <= p;i++) deal(i,1);

        int now = p;
        double re = 0;
        while(1)
        {
            re += num[1];
            now++;if(now > n) break;
            deal(now,1);
            deal(now-p,-1);
        }
        printf("%.2f\n",re / (n-p+1));
    }
    return 0;
}
zoj 3598 Spherical Triangle 计算几何,跳过,自己不会!

zoj 3599 Game 博弈,这一套题中居然有两个博弈!!!真心不知道出题者怎么想的。

但是这个题的博弈真心的很难!!!!现在只知道结论,但是不知道为什么!!给了一个英文的网址,可是真心的看不懂

/*
zju比赛时被gao了,半天找不到好的规律,特在次几下这一类的博弈问题通解。
一个石子堆,先手不能全部取玩,每次取石子数在[1,f(前一次取的石子数)],f(x) >= x;
H(1) = 1,H(k+1) = H(k) + H(m),m = min{ j | f( H(j) ) >= H(k)}。
该数列为所有必败局面。
目前只知其然,不知其所以然。
*/
#include <iostream>
using namespace std;

long long data[1000000];

long long deal(int m,int n)
{
    data[1] = 1;
    int pre = 1;
    for(int k = 2;;k++)
    {
        int j;
        for(j = pre;j < k;j++) if(data[j]*m >= data[k-1]) break;
        pre = j;
        data[k] = data[k-1]+data[j];
        cout << data[k] << " " ;
        //cout << n << " " << k << " \n " ;
        if(data[k] > n) return n-k+1;
    }
    return 0;
}
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        int m,n;
        cin >> m >> n;
        cout << deal(m,n) << "\n";
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值