• 【日常】暑假7天培训


    Day1

    早上8:00上课

    7:40还在家里的我(颓

    匆匆忙忙地到了学校(本校)

    去了趟宿舍放东西

    8:10左右到了教室

    迟到了一小会没有听到wbs老师的自我介绍

    感觉他好可爱

    我以为我是最迟的......没想到hyc大佬更迟......

    第一天就上数论感觉要被劝退回隔壁pj组了

    各种奇怪的定理wbs老师说只是简单的复习罢了......然而蒟蒻我脑子要炸了......

    大概讲了扩欧 中国剩余定理 分块优化 欧拉函数 莫比乌斯函数 积性函数啥的

    然后就没听懂几个

    感觉被吊打......

    中午12:00

    宿舍吃鸡

    前两天都好迟睡中午又没睡 感觉眼睛超级酸

    下午考试毫无状态

    T1

    用数论推一推

    大概是用分块写吧

    考试代码(90分):

    #include <iostream>
    #include<cstdio>
    using namespace std;
    long long n,k,ans,r,t;
    int main()
    {
        freopen("sum.in","r",stdin);
        freopen("sum.out","w",stdout);
        cin>>n>>k;
        for(long long l=1;l<=n;l=r+1)
        {
            r=(t=k/l)?(k/t):n;
            ans-=t*(r-l+1)*(l+r)>>1;
        }
        cout<<ans+n*k;
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    忘记加一个取最小值然后超限了

    #include <iostream>
    #include<cstdio>
    using namespace std;
    long long n,k,ans,r,t;
    int main()
    {
        cin>>n>>k;
        for(long long l=1;l<=n;l=r+1)
        {
            r=(t=k/l)?min((k/t),n):n;//取最小
            ans-=t*(r-l+1)*(l+r)>>1;
        }
        cout<<ans+n*k;
    }
    View Code

    T2

    当P是质数的时候裸扩欧

    不是的时候就不会了......

    考试的时候就打了扩欧骗骗分

    扩欧证明:https://www.cnblogs.com/BrokenString/p/9275595.html

    考试代码(0分):

    #include<iostream>
    #include<cstdio>
    using namespace std;
    void exgcd(int a,int b,int &x,int &y)
    {
         if(b==0)
        {
            x=1;
            y=0;
            return;
        }
        exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
    int main()
    {
        freopen("equation.in","r",stdin);
        freopen("equation.out","w",stdout);
        int t;
        cin>>t;
        for(int i=1;i<=t;i++)
        {
            int x,y,a,b,c;
            cin>>a>>c>>b;
            exgcd(a,b,x,y);
            cout<<x;
        }
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    看不懂

    大概是Ax+Cy=B

    然后B是gcd(A,C)的倍数推一下用扩欧

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long ll;
    int gcd(int a,int b){
        if(a<b) swap(a,b);
        while(b) swap(a%=b,b);
        return a;
    }
    void exgcd(int a,int b,ll &x,ll &y){
        if(!b){x=1,y=0;return;}
        ll p,q;exgcd(b,a%b,p,q);
        x=q,y=p-a/b*q;
    }
    int solve(int a,int b,int p){
        a%=p,b%=p;
        if(!a){
            if(b) return -1;
            return 0;
        }
        int d=gcd(a,p);ll x,y;
        if(b%d) return -1;
        exgcd(p,a,x,y);
        int g=y%p*(b/d)%p;
        return g<0?g+p:g;
    }
    int main(){
        freopen("equation.in","r",stdin);
        freopen("equation.out","w",stdout);
        int T,a,p,b;
        for(scanf("%d",&T);T--;){
            scanf("%d%d%d",&a,&b,&p);
            a%=p,b%=p;
            int x=solve(a,b,p);
            if(x==-1) puts("No Solution");
            else printf("%d
    ",x);
        }
        return 0;
    }
    View Code

    T3

    这是什么鬼 完全没思路

    然后打了个随机输出十以内的数骗分

    考试代码(0分):

    #include<iostream>
    #include<cstdlib>
    #include<ctime>
    #include<cstdio>
    using namespace std;
    int main()
    {
        freopen("gcd.in","r",stdin);
        freopen("gcd.out","w",stdout);
        srand((unsigned)time(NULL));
        cout<<rand()%10<<' ';
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

     每次取最小值乘上另一个值后加入这个值

    把另外两个数删掉

    #include<stdio.h>
    int n,t,p[1250],res,tmp;
    bool v[10001];
    int main()
    {
        freopen("gcd.in","r",stdin);
        freopen("gcd.out","w",stdout);
        scanf("%d",&n);
        for(int i=2;i<=n;++i)
            if(!v[i]){
                p[++t]=i;
                for(int j=i;j<=n;j+=i) v[j]=1;
            }
        for(int l=1,r=t;l<=r;--r){
            tmp=p[r];
            while(l<=r&&tmp*p[l]<=n) tmp*=p[l++];
            ++res;
        }
        printf("%d",res);
    }
    View Code

    晚上6:00开始晚自习

    晚上就做了一道扩欧的模板题 写了一下题解啥的

    然后wbs老师走了以后就开始和hyc大佬悄咪咪的吃鸡

    回宿舍后看了蜘蛛侠3就24:00了

    补觉zzz......


     Day2

    早上7:40多起床

    匆忙啃了几口面包就跑到机房去了

    早上上了贪心 分治 树状数组 Huffman编码 KMP 还有一堆完全听不懂的高数和概率期望

    一早上听不懂强行理解下来感觉脑子要bang

    中午偷偷吃泡面看钢铁侠3半小时

     T1:

    考试的时候到是想到了

    每次取2个最小值加起来的值放回原集合中

    30分钟打完

    考试代码(100分):

    #include<iostream>
    #include<cstdio>
    #include <queue>
    using namespace std;
    priority_queue<int, vector<int>, greater<int> > H;
    long long n,ans;
    long long len[200005];
    int main()
    {
        freopen("cut.in","r",stdin);
        freopen("cut.out","w",stdout);
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>len[i];
            H.push(len[i]);
        }
        while(H.size()>1)
        {
            int k=0;
            k+=H.top();
            H.pop();
            k+=H.top();
            H.pop();
            ans+=k;
            if(H.empty())
            break;
            H.push(k);
        }
        cout<<ans;
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    T2:

    树状数组并不会

    乱搞20分

    考试代码(20分):

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    int a[10010];
    int dp[10010];
    int main()
    {
        freopen("choose.in","r",stdin);
        freopen("choose.out","w",stdout);
        int n,m;
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            dp[i]=1;
        }
        int ans=0;
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(a[j]<a[i])
                {
                    dp[i]=max(dp[j]+1,dp[i]);
                }
            }
            ans=max(ans,dp[i]);
        }
        int k=n-ans;
        if(k>=m)
        printf("%d",ans);
        else
        {
            ans-=m-k;
            printf("%d",ans);
        }
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=100002;
    inline int get(){
        char ch;while(!isdigit(ch=getchar()));
        int x=ch-48;
        while(isdigit(ch=getchar()))
            x=(x<<3)+(x<<1)+ch-48;
        return x;
    }
    int n,m,ta[N],a[N],f1[N],f2[N],bit[N];
    int main(){
        freopen("choose.in","r",stdin);
        freopen("choose.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) ta[i]=a[i]=get();
        sort(ta+1,ta+n+1);
        int l=unique(ta+1,ta+n+1)-ta-1;
        for(int i=1;i<=n;++i)
            a[i]=lower_bound(ta+1,ta+l+1,a[i])-ta;
        for(int i=1;i<=n;++i){
            int ret=0;
            for(int j=a[i]-1;j;j-=j&-j)
                ret=max(ret,bit[j]);
            f1[i]=ret+1;
            for(int j=a[i];j<=l;j+=j&-j)
                bit[j]=max(bit[j],f1[i]);
        }
        memset(bit+1,0,l<<2);
        for(int i=n;i;--i){
            int ret=0;
            for(int j=a[i]+1;j<=l;j+=j&-j)
                ret=max(ret,bit[j]);
            f2[i]=ret+1;
            for(int j=a[i];j;j-=j&-j)
                bit[j]=max(bit[j],f2[i]);
        }
        memset(bit+1,0,l<<2);
        int ans=0,len=n-m+1;
        f1[0]=f2[n+1]=0,a[n+1]=l+1;
        for(int i=1;i<=len;++i){
            int ret=0;
            for(int j=a[i+m]-1;j;j-=j&-j)
                ret=max(ret,bit[j]);
            ans=max(ans,ret+f2[i+m]);
            for(int j=a[i];j<=l;j+=j&-j)
                bit[j]=max(bit[j],f1[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    T3:

    KMP题

    并不会

    直接放弃

    考试代码(0分):

    #include<iostream>
    #include<cstdio>
    #include<string>
    using namespace std;
    int main()
    {
        while(~scanf("%s",a))
        {
            string a;
            string b;
            cin>>a;
            b[0]=a[0];
            for(int i=1;i<a.size();i++)
            {
                b[i]=a[i];
                while(a[i]==a[1])
                {
                        
                }
                if(b.size()==a.size())
                {
                    cout<<1<<endl;
                    break;
                }
            }
        }
    }
    View Code

    正解:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int maxn = 1000005;
    int next[maxn];
    void get(char *s) 
    {
        int l=strlen(s);
        int j=0,k=-1;
        next[0]=-1;
        while(j<l) 
        {
            if(k == -1 || s[j] == s[k])
            {
                next[++j]=++k;
            } 
            else
            {
                k = next[k];
            }
        }
    }
    char s[maxn];
    int main() 
    {
        freopen("string.in","r",stdin);
        freopen("string.out","w",stdout);
        while(~scanf("%s",s) ) 
        {
            get(s);
            int ans=1;
            int l=strlen(s);
            if(l%(l-next[l])==0) 
            {
                ans=l/(l-next[l]);
            }
            printf("%d
    ",ans);
        }
    }
    View Code

     晚上

    敲了一下KMP的板子

    还有树状数组1 2的板子

    晚上看了一部钢铁侠3

    呼哧呼哧睡觉~


    Day3

    早上8:00到机房

    发现机房只有我们学校的人了???

    原来其他学校的人都被劝退到隔壁PJ了???

    好吧我承认有的我也听不懂

    早上上了一堆的暴搜

    还有DFS序 迭代加深 A* 一些物理题???

    看了几道题目贼长的暴搜感觉脑子炸once again

     中午12:00

    在食堂吃饭下大雨被困住

    三个瓜皮跑到旁边宿舍躲雨吃鸡

    下午考试

    T1:

    被wbs老师耍了一波......

    说好的题目不用树状数组的咧?

    然后啪啦啪啦打了2h

    还TM多打了测试时用的序列(我好菜啊

    考试代码(0分):

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m;
    struct edge
    {
        int pre;
        int next;
        int to;
    }e[100010];
    int f[100010];
    int ans[100010];
    int xu[100010];
    int head[100010];
    int sum;
    void add(int x,int y)
    {
        e[++m].pre=x;
        e[m].to=y;
        e[m].next=head[x];
        head[x]=m;
    }
    void dfs(int x)
    {
        xu[++sum]=x;
        int u=head[x];
        if(u==0)
        return;
        while(u!=0)
        {
            dfs(e[u].to);
            f[x]+=f[e[u].to]+1;
            u=e[u].next;
        }
    }
    int main()
    {
        freopen("tree.in","r",stdin);
        freopen("tree.out","w",stdout);
        cin>>n;
        for(int i=2;i<=n;i++)
        {
            int x;
            cin>>x;
            add(x,i); 
        }
        dfs(1);
        for(int i=1;i<=n;i++)
        cout<<xu[i]<<" ";
        cout<<endl;//多输出这行少了30分
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=i+f[xu[i]];j++)
            {
                if(xu[j]<xu[i])
                ans[xu[i]]++;
            }
        }
        for(int i=1;i<=n;i++)
        cout<<ans[i]<<" ";
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    要用树状数组啥的

    没弄出来

    T2:

    早上上的例题然而并不会

    埃及分数迭代加深

    考试时放弃(0分)

    正解:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #define N 1000
    using namespace std;
    
    long long ans[N],s[N],mo,ch;
    int dep;
    long long gcd(long long a,long long b){return b==0?a:gcd(b,a%b);}
    void outp()
    {
        int i;
        if (ans[dep]>s[dep])
            {
                for (i=1;i<=dep;i++)
                {
                    ans[i]=s[i];
                }
            } 
    }
    void dfs(long long x,long long y,int d)
    {
        long long a,b,i,w;
        if (d==dep)
        {
            s[d]=y;
            if ((x==1)&&(s[d]>s[d-1])) outp();
            return;
        }
        for (i=max(s[d-1]+1,y/x+1);i<(dep-d+1)*y/x;i++)
        {
            b=y*i/gcd(y,i);
            a=b/y*x-b/i;
            w=gcd(a,b);
            a/=w;
            b/=w;
            s[d]=i;
            dfs(a,b,d+1);
        }
    }
    int main()
    {
        int i=0,j;
        scanf("%lld%lld",&ch,&mo);
        i=gcd(ch,mo);
        ch/=i;
        mo/=i;
        for (dep=2;;dep++)
        {
            ans[1]=0;
            s[0]=0;
            ans[dep]=2000000000;
            dfs(ch,mo,1);
            if (ans[1]!=0) break;
        }
        for (j=1;j<=dep;j++)
        {
            printf("%lld ",ans[j]);
        }
        printf("
    ");
        return 0;
    }
    View Code

    T3:

    一道闲得蛋疼的物理题......

    前70分暴力求公式

    后三十分用调和函数大数公式

    由于边加边乘少了30

    考试代码(40分):

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    using namespace std;
    double n,l,ans;
    int main()
    {
        freopen("book.in","r",stdin);
        freopen("book.out","w",stdout);
        cin>>n>>l;
        for(double i=1;i<=n;i++)
        {
            ans+=1/(2*i)*l;
        }
        printf("%.4f",ans);
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    没写......

    晚上晚自习

    wbs老师说他要回厦大上课了

    苦逼......

    明天来上课的是他的学长gtc

    他说我们不要再迟到了

    不给他面子也要给gtc面子

    害怕......

    晚上看美国队长3

     Day4

    早上上计算几何

    大多都是高中数学

    划了一早上的水......

    早上的课已经听过三遍了

    然而代码还是不会写

    中午日常吃鸡

    听说下午gtc老师要给我们信心

    出得简单点

    T1:

    判读两条直线是否有交点

    裸裸地套公式(然而蒟蒻写的太长看错了

    考试代码(10分):

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,ans;
    float p[101][3][3];
    void cross(int i,int j)
    {
        if(((p[j][1][1]-p[i][1][1])*(p[i][2][2]-p[i][1][2])-(p[i][2][1]-p[i][1][1])*(p[j][1][2]-p[i][1][2]))*((p[i][2][1]-p[i][1][1])*(p[j][2][2]-p[i][1][2])-(p[i][2][1]-p[i][1][1])*(p[j][2][2]-p[i][1][2]))>=0)
        if(((p[i][1][1]-p[j][2][1])*(p[j][1][2]-p[j][2][2])-(p[j][1][1]-p[j][2][1])*(p[i][1][2]-p[j][2][2]))*((p[j][1][1]-p[j][2][1])*(p[i][2][2]-p[j][2][2])-(p[i][2][1]-p[j][2][1])*(p[j][1][2]-p[j][2][2]))>=0)
           ans++;
        return;
    }
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>p[i][1][1]>>p[i][1][2]>>p[i][2][1]>>p[i][2][2];
            for(int j=1;j<i;j++)
            cross(i,j);
        }
        cout<<ans;
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    有一个点卡精度

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,ans;
    double p[101][3][3];
    int t(double a) {
        if (fabs(a) < 1e-5) return 0;
        return a > 1e-5 ? 1 : -1;//因为只要判断符号所以1或-1即可 
    }
    void cross(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)
    {
        if(t((x3-x1)*(y2-y1)-(x2-x1)*(y3-y1))*t((x2-x1)*(y4-y1)-(x4-x1)*(y2-y1))>=0)
        if(t((x1-x4)*(y3-y4)-(x3-x4)*(y1-y4))*t((x3-x4)*(y2-y4)-(x2-x4)*(y3-y4))>=0)
        ans++;
    }
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>p[i][1][1]>>p[i][1][2]>>p[i][2][1]>>p[i][2][2];
            for(int j=1;j<i;j++)
            cross(p[j][1][1],p[j][1][2],p[j][2][1],p[j][2][2],p[i][1][1],p[i][1][2],p[i][2][1],p[i][2][2]);
        }
        cout<<ans;
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    T2:

    判断点到线的距离

    暴力写了部分分

    考试代码(40分):

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,r,ans;
    float p[50050][3];
    int pd(int x,int y)
    {
        float x1=p[x][1];
        float y1=p[x][2];
        float x2=p[y][1];
        float y2=p[y][2];
        return (0-x1)*(x2-x1)+(0-y1)*(y2-y1);
    }
    float cross(float x1,float y1,float x2,float y2)
    {
        float d=x1*y2-x2*y1;
        if(d>=0)
        return d;
        return -d;
    }
    float dis(float x1,float y1,float x2,float y2)
    {
        return sqrt(pow(x1-x2,2)+pow(y1-y2,2));
    }
    int main()
    {
        freopen("b.in","r",stdin);
        freopen("b.out","w",stdout);
        cin>>n>>r;
        for(int i=1;i<=n;i++)
        cin>>p[i][1]>>p[i][2];
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(pd(i,j)<0||pd(j,i)<0)
            {
                float d=min(pow(p[i][1],2)+pow(p[i][2],2),pow(p[j][1],2)+pow(p[j][2],2));
                if(d>(r*r))
                ans++;
            }
            else
            {
                float d=cross(p[i][1],p[i][2],p[j][1],p[j][2])/dis(p[i][1],p[i][2],p[j][1],p[j][2]);
                if(d>r)
                ans++;
            }
        }
        cout<<ans;
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    gtc老师说本来就没打算有人写出来......

    要在圆弧上求区间交

    好厉害的样子啊

    并没有标程(太难了

    T3:

    裸裸地凸包模板

    考试代码(100分):

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n;
    struct point
    {
        float x;
        float y;
    }p[10010];
    int q[40040];
    int top;
    float cross(float x1,float y1,float x2,float y2)
    {
        float d=x1*y2-x2*y1;
        return d;
    }
    bool cmp(point a,point b)
    {
        if(a.x!=b.x)
        return a.x<b.x;
        else
        return a.y<b.y;
    }
    int main()
    {
        freopen("c.in","r",stdin);
        freopen("c.out","w",stdout);
        cin>>n;
        for(int i=1;i<=n;i++)
        cin>>p[i].x>>p[i].y;
        sort(1+p,1+p+n,cmp);
        for(int i=1;i<=n;i++)
        {
            while(top>=2&&cross(p[q[top-1]].x-p[q[top]].x,p[q[top-1]].y-p[q[top]].y,p[q[top-1]].x-p[i].x,p[q[top-1]].y-p[i].y)<=0)
            top--;
            q[++top]=i;
        }
        int k=top;
        for(int i=n-1;i>=1;i--)
        {
            while(top>k&&cross(p[q[top-1]].x-p[q[top]].x,p[q[top-1]].y-p[q[top]].y,p[q[top-1]].x-p[i].x,p[q[top-1]].y-p[i].y)<=0)
            top--;
            q[++top]=i;
        }
        if(n>1)
        top--;
        cout<<top;
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    晚上机房划水

    回宿舍看银河护卫队

    Day5

    早上起迟了......

    8:00起床 然而8:00就上课了

    gtc老师的课迟到真的很不好意思啊

    一早上的DP 脑子又炸了

    状压DP还是不太懂

    T1:

    第一题挺水的

    40min敲完线性DP

    考试代码(100分):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    char s1[2005],s2[2005];
    int f[2005][2005];
    int n,m;
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        scanf("%s%s",s1,s2);
        n=strlen(s1);
        m=strlen(s2);
        for(int i=1;i<=n;i++)
        f[i][0]=i;
        for(int i=1;i<=m;i++)
        f[0][i]=i;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(s1[i-1]==s2[j-1])
            f[i][j]=f[i-1][j-1];
            else
            {
                f[i][j]=min(f[i][j-1]+1,f[i-1][j]+1);
                f[i][j]=min(f[i][j],f[i-1][j-1]+1);
            }
        }
        cout<<f[n][m];
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    T2:

    说好的都考DP呢?

    又被耍了一波

    把正解给改成超时的了.......(难受

    考试代码(40分):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,sum,ans=1;
    int f[1000010];
    struct maps
    {
        int h;
        int x;
        int y;
    }map[1000010];
    bool cmp(maps a,maps b)
    {
        return a.h<b.h;
    }
    int pd(int i,int j)
    {
        if(map[i].x+1==map[j].x&&map[i].y==map[j].y) return 1;
        if(map[i].x-1==map[j].x&&map[i].y==map[j].y) return 1;
        if(map[i].x==map[j].x&&map[i].y+1==map[j].y) return 1;
        if(map[i].x==map[j].x&&map[i].y-1==map[j].y) return 1;
        return 0;
    }
    int main()
    {
        freopen("b.in","r",stdin);
        freopen("b.out","w",stdout);
        cin>>n>>m;
        for(int i=1;i<=n*m;i++)
        f[i]=1;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cin>>map[++sum].h;
            map[sum].x=i;
            map[sum].y=j;
        }
        sort(1+map,1+map+n*m,cmp);
        for(int i=2;i<=n*m;i++)
        {
            for(int j=1;j<i;j++)
            {
                if(pd(i,j)&&map[i].h>map[j].h)
                {
                    f[i]=max(f[i],f[j]+1);
                }
            }
            ans=max(ans,f[i]);
        }
        cout<<ans;
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    要把cincout改成scanf啥的

    不然会T6个点

    #include<iostream>
    #include<cmath>
    using namespace std;
    int a[201][201];
    int b[201][201];
    int dx[4]={0,0,1,-1},
        dy[4]={1,-1,0,0};
    int n,m;
    int maxn=0;
    int search(int x,int y)
    {
        if(b[x][y])
        return b[x][y];
        b[x][y]=1;
        for(int i=0;i<4;i++)
        {
            int x1=x+dx[i];
            int y1=y+dy[i];
            if(x1>=1&&x1<=n&&y1>=1&&y1<=m&&a[x1][y1]>a[x][y])
            b[x][y]=max(b[x][y],1+search(x1,y1));
        }
        return b[x][y];
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        cin>>a[i][j];
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            maxn=max(maxn,search(i,j));
        }
        cout<<maxn;
    }
    View Code

    T3:

    说好的状压呢?

    虽然就算是状压也不会写

    暴力打表过了2个点

    考试代码(20分):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mod 9999973;
    using namespace std;
    int n,m;
    int main()
    {
        freopen("c.in","r",stdin);
        freopen("c.out","w",stdout);
        cin>>n>>m;
        if(n==1)
        {
            for(int i=1;i<=8;i++)
            if(m==i)
            cout<<(1+m-1)*(m-1)/2+m+1;
        }
        if(n==2)
        {
            for(int i=1;i<=8;i++)
            if(m==i)
            cout<<((1+m-1)*(m-1)/2+m+1)*2;
        }
        else
        cout<<666;
        fclose(stdin);
        fclose(stdout);
    }
    View Code

    正解:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int MAXN = 101;
    const int MOD = 9999973;
    int n,m;
    ll dp[MAXN][MAXN][MAXN];
    inline int C( int num ) { // 相当于C(num,2)
        return num*(num-1)/2;
    }
    int main() {
        scanf( "%d%d", &n, &m );
        dp[0][0][0] = 1;
        for( int i = 0; i < n; ++i ) // 放第i+1行
        for( int j = 0; j <= m; ++j ) // 有1个棋子的列数
        for( int k = 0; j+k <= m; ++k ) if( dp[i][j][k] ) { // 有2个棋子的列数
            dp[i+1][j][k] = ( dp[i+1][j][k] + dp[i][j][k] ) % MOD; // 不放
            if( m-j-k >= 1 ) dp[i+1][j+1][k] = ( dp[i+1][j+1][k] + dp[i][j][k]*(m-j-k) ) % MOD; // 放一个,在没有棋子的那一列
            if( j >= 1 ) dp[i+1][j-1][k+1] = ( dp[i+1][j-1][k+1] + dp[i][j][k]*j ) % MOD; // 放一个,在有一个棋子的那一列
            if( m-j-k >= 2 ) dp[i+1][j+2][k] = ( dp[i+1][j+2][k] + dp[i][j][k]*C(m-j-k) ) % MOD; // 放两个,都在没有棋子的两列
            if( m-j-k >= 1 && j >= 1 ) dp[i+1][j][k+1] = ( dp[i+1][j][k+1] + dp[i][j][k]*(m-j-k)*j ) % MOD; // 放两个,一个在没有棋子的列,一个在有一个棋子的列
            if( j >= 2 ) dp[i+1][j-2][k+2] = ( dp[i+1][j-2][k+2] + dp[i][j][k]*C(j) ) % MOD; // 两个,在一个棋子的列
        }
        ll ans = 0;
        for( int i = 0; i <= m; ++i ) // 有1个棋子的列
        for( int j = 0; i+j <= m; ++j ) { // 2个棋子的列
            ans = ( ans + dp[n][i][j] ) % MOD;
        }
        printf( "%lld
    ", ans );
        return 0;
    }
    View Code

     下午下课加了gtc老师的QQ

    人挺好的(原来以为很凶的样子

    说我们有事可以问他

    他要去福州上课了

    跟我们说了再见

    晚上机房没老师管

    又颓了一波

    Day6


    今天老师换成sjh老师啦

    看起来好像......蛮有代沟的样子(不像大学生啊

    来自中国科学院大学???

    据说是一个比清北还要牛逼的大学(崇拜脸

    早上上图论

    又是划水的一天

    唯一想听的差分约束系统竟然这么简单???

    虽然思路都会

    但是好久没做图论板子都忘光光了额......

    T1:

    裸的最短路

    算了一下最简单的Floyed好像不会超时

    但是......但是它还是爆了只有40分(我好菜啊

    考试代码(40分):

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,m;
    float len;
    float ele[1005][3];
    float map[1005][1005];
    float pd(float x1,float y1,float x2,float y2,float x3,float y3)
    {
        if(pow(x3-x2,2)+pow(y3-y2,2)>=pow(len,2))
        return 0;
        if(pow(x3-x1,2)+pow(y3-y1,2)>=pow(len,2))
        return 0;
    }
    float dis(int f,int s)
    {
        float x1=ele[f][1];
        float y1=ele[f][2];
        float x2=ele[s][1];
        float y2=ele[s][2];
        float d=sqrt(pow(x1-x2,2)+pow(y1-y2,2));
        return d;
    }
    int main()
    {
        scanf("%d%d%f",&n,&m,&len);
        for(int i=1;i<=n;i++)
        cin>>ele[i][1]>>ele[i][2];
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(i==j)
            map[i][j]=map[j][i]=0;
            else
            {
                if(dis(i,j)>len)
                map[i][j]=map[j][i]=99999999;
                else
                map[i][j]=map[j][i]=dis(i,j);
            }
        }
        for(int i=1;i<=m;i++)
        {
            int x,y;
            cin>>x>>y;
            map[x][y]=0;
            map[y][x]=0;
        }
        for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j-++)
        {
            if(map[i][j]>map[i][k]+map[k][j])
            map[i][j]=map[i][k]+map[k][j];
        }
        if(map[1][n]==99999999)
        cout<<"-1";
        else
        cout<<floor(map[1][n]*1000);
    }
    View Code

    正解:

    用SPFA做最短路

    或者Floyed砍掉一半边

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,m,cnt;
    double ans,len;
    int exist[500005];
    int team[2000020];
    int head[500005];
    double dis[500005];
    int t=0,w=1;
    struct ele
    {
        double x;
        double y;
    }ele[100005];
    struct edge
    {
        int next;
        int to;
        double w;
    }e[5000005];
    void add(int u,int v,double w)
    {
        e[++cnt].w=w;
        e[cnt].to=v;
        e[cnt].next=head[u];
        head[u]=cnt;
    }
    double dist(int i,int j)
    {
        double x1=ele[i].x;
        double y1=ele[i].y;
        double x2=ele[j].x;
        double y2=ele[j].y;
        double d=hypot(x1-x2,y1-y2);
        return d;
    }
    int main()
    {
        cin>>n>>m>>len;
        for(int i=1;i<=n;i++)
        cin>>ele[i].x>>ele[i].y;
        for(int i=1;i<=n;i++)
        dis[i]=99999999;
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(dist(i,j)<=len)
            {
                add(i,j,dist(i,j));
                add(j,i,dist(i,j));
            }
        }
        for(int i=1;i<=m;i++)
        {
            int x,y;
            cin>>x>>y;
            add(x,y,0);
            add(y,x,0);
        }
        dis[1]=0;
        team[1]=1;
        while(t<w)
        {
            t++;
            int u=team[t];
            exist[u]=0;
            for(int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].w)
                {
                    dis[v]=dis[u]+e[i].w;
                    if(!exist[v])
                    {
                        w++;
                        exist[v]=1;
                        team[w]=v;
                    }
                }
            }
        }
        if(dis[n]==99999999)
        cout<<"-1";
        else
        cout<<int(dis[n]*1000);
    }
    View Code

    T2:

    最大流......

    思路完全正确(代码完全忘却

    打了个表和随机数

    考试代码(10分):

    #include<iostream>
    #include<cstdlib>
    #include<ctime>
    #include<cstdio>
    using namespace std;
    int n,k;
    bool f[21][21];
    int main()
    {
        scanf("%d%d",&n,&k);
        if(k==0)
        cout<<n;
        else
        {
            if(k==1)
            cout<<1;
            else
            {
                 srand((unsigned)time(NULL));
                 cout<<rand()%10<<' ';
            }
        }
    }
    View Code

    正解:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<deque>
    #include<cstring>
    #define INF 1e9
    using namespace std;
    int n,k,S,T,V[120000],nex[120000],las[4000],W[120000],c[4000],tot=1,L=0,R=1e9;
    char s[550][550];
    void addedge(int t1,int t2,int t3)
    {
        V[++tot]=t2;nex[tot]=las[t1];las[t1]=tot;W[tot]=t3;
        V[++tot]=t1;nex[tot]=las[t2];las[t2]=tot;W[tot]=0;
    }
    bool bfs()
    {
        bool flag=0;
        deque<int>que;
        que.clear();
        memset(c,0,sizeof(c));
        c[S]=1;que.push_back(S);
        while(!que.empty())
        {
            int x=que.front();que.pop_front();
            if(x==T)flag=1;
            int h=las[x];
            while(h)
            {
                if(W[h]>0&&!c[V[h]])
                    c[V[h]]=c[x]+1,que.push_back(V[h]);
                h=nex[h];
            }
        }
        return flag;
    }
    int dfs(int x,int p)
    {
        if(x==T||!p)return p;
        int flow=0,fl;
        for(int i=las[x];i;i=nex[i])
            if(c[x]+1==c[V[i]]&&W[i])
            {
                fl=dfs(V[i],min(p-flow,W[i]));
                flow+=fl;W[i^1]+=fl;W[i]-=fl;
                if(flow==p)return flow;
            }
        return flow;
    }
    bool build(int mid)
    {
        memset(las,0,sizeof(las));
        memset(W,0,sizeof(W));
        memset(V,0,sizeof(V));
        memset(nex,0,sizeof(nex));
        tot=1;
        for(int i=1;i<=n;++i)lj(S,i,mid);
        for(int i=2*n+1;i<=3*n;++i)lj(i,T,mid);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
            {
                if(s[i][j]=='Y')lj(i,2*n+j,1);
                else
                {
                    lj(n+i,3*n+j,1);
                }
            }
        for(int i=1;i<=n;i++)lj(i,i+n,k),lj(3*n+i,2*n+i,k);
        int ans=0;
        while(bfs())ans+=dfs(S,INF);
        return (ans==mid*n);
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        S=4*n+1;T=4*n+2;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)scanf(" %c",&s[i][j]);
        while(L<R)
        {
            int mid=(L+R+1)>>1;
            if(build(mid))L=mid;
            else R=mid-1;
        }
        printf("%d",L);
        return 0;
    }
    View Code

    T3:

    完全没有思路......

    考试放弃

    正解:

    用一种玄学的进制存图

    然后上下移动不管 因为反正都要走回去

    所以观察左右移动就行

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define N 55
    #define inf 1e9
    int n,m,map[N][N],tot,toti,MaxS,f[N][N][1050],g[N][N],ok,ans[12];
    int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; //四个方向走 
    bool inq[N][N][1050];char c[N][N];
    struct node
    {
        int x,y,S;
        node(){};
        node(int _x,int _y,int _S) {x=_x,y=_y,S=_S;}
    };
    queue<node>q;
    int main(){
    //    freopen("1.in","r",stdin); 
        while(scanf("%s",c[++n]+1)!=EOF);
        m=strlen(c[--n]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(c[i][j]!='.'){
                    //tot 非.格子的个数,toti i格子的个数 
                    map[i][j]=++tot;
                    if(c[i][j]=='X') 
                        //二进制,1对应的那位为X 
                        ok|=1<<tot-1;
                    else 
                        toti++;
                }
        //map数组表示从ij格子先向上j走到0,再i走到0,新圈住的非.格
        //例如样例:
        //102
        //142
        //942 
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                g[i][j]=g[i-1][j];
                if(map[i][j]) g[i][j]|=1<<map[i][j]-1;
            }
        MaxS=(1<<tot)-1;
        //f[i][j][k]表示从ij格子返回来圈主k(二进制有多少个1)个 非.格子所走的步数 
        //inq数组表示是否访问过 
        for(int i=0;i<=n;i++)
            for(int j=0;j<=m;j++)
                for(int k=0;k<=MaxS;k++) f[i][j][k]=inf;
        f[0][0][0]=0,inq[0][0][0]=1,q.push(node(0,0,0));
        
        while(!q.empty()){
            node top=q.front();
            q.pop();
            inq[top.x][top.y][top.S]=0;
            cout<<top.x<<"-"<<top.y<<"-"<<top.S<<":"<<f[top.x][top.y][top.S]<<endl;
            for(int k=1;k<=4;k++){
                int nx=top.x+dx[k],ny=top.y+dy[k],nS=top.S;
                if(nx<0||nx>n||ny<0||ny>m) continue;
                //假设到xy点后,返回都是先走y再走x,所以只需要更新k=3和4 
                //3往左走判断左边格子新圈住的非.格子 
                if(k==3) nS^=g[top.x][top.y];
                //4往右走判断右边格子新圈住的非.格子
                if(k==4) nS^=g[nx][ny];
                //更新f数组 
                if(f[nx][ny][nS]>f[top.x][top.y][top.S]+1){
                    f[nx][ny][nS]=f[top.x][top.y][top.S]+1;
                    //打标记,当前状态没访问过则入队列 
                    if(!inq[nx][ny][nS])
                        inq[nx][ny][nS]=1,q.push(node(nx,ny,nS));
                }
            }
        }
        for(int i=1;i<=toti;i++) ans[i]=inf;
        for(int i=0;i<=MaxS;i++)
            if(!(i&ok)){
                int cnt=0;
                //计算多少个I, 
                for(int j=0;j<tot;j++) if((i>>j)&1) cnt++;
                //f[0][0][i]表示圈主i对应二进制为1的I所需的步数 
                ans[cnt]=min(ans[cnt],f[0][0][i]);
            }
        for(int i=1;i<=toti;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    View Code

    晚上台风 没去吃饭

    没有电影看好无聊啊

    晚上偷吃泡面

    Day7

    最后一天的早上

    又迟到了

    早上前面一个小时讲了Day6的几道题

    还有图论的几道例题

    然后上了数据结构 线段树啥的

    但是!

    我最想听的ST表和树上倍增居然因为时间不够没讲了QAQ

    中午没怎么休息 因为下午4点就可以回家

    13:00就开始考试了

    T1

    哇这最小公倍数水水的

    T2

    哇这题看不懂打个暴力30分

    T3

    哇这不是SPFA微调一下就可以了

    结果......爆零......

    T1谜一样的后来对了标程

    除了定义不一样 其他都一样 可是莫名其妙的结果被零整除???

    T2就一点点的数据超内存???

    T3一开始没想到正解 原来是最小生成树

    培训就在这最谜的一天结束了......

  • 相关阅读:
    jQuery easyUI 的combogrid进行模糊匹配
    SQL 快速生成不重复的卡号
    用SQL语句查找包含有某个关键字的存储过程、触发器、函数等等
    C# DateTime日期格式化
    【SQL触发器】类型 FOR 、AFTER、 Instead of
    【BAT】批量给制定类型的文件名添加前缀
    【VBA】将Excel数据转化为txt文本数据
    【Python】将多个工作簿中的数据按列合并到同一个工作表
    【Python】从DB2数据库中取出字段信息并根据字段类型生成SQL
    【Oracle】多行数据合并为一行,使用逗号分隔
  • 原文地址:https://www.cnblogs.com/BrokenString/p/9274459.html
Copyright © 2020-2023  润新知