【日常】暑假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\n",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\n",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\n",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("\n");
    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\n", 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\n",ans[i]);
    return 0;
}
View Code

晚上台风 没去吃饭

没有电影看好无聊啊

晚上偷吃泡面

Day7

最后一天的早上

又迟到了

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

还有图论的几道例题

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

但是!

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

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

13:00就开始考试了

T1

哇这最小公倍数水水的

T2

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

T3

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

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

T1谜一样的后来对了标程

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

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

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

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

posted @ 2018-07-08 19:21  Nanchtiy  阅读(362)  评论(7编辑  收藏  举报