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;
}


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com