czl蒻蒟的OI之路16

来源:互联网 发布:matlab 矩阵[ ] 编辑:程序博客网 时间:2024/05/16 12:32

  • XJOI奋斗群蒻蒟群群赛17 RANK排名9
      • T1Increasing SequenceTLE一次AC
          • 题意
          • 分析过程
          • 给出题解
      • T2Jumping JackWA一次后AC
          • 题意
          • 分析过程
          • 给出题解
      • T3How Many Squares 已AC
          • 题意
          • 分析过程
          • 给出题解
      • T4A Simple TaskWA两次之后AC
          • 题意
          • 分析过程
          • 给出题解
      • T5
          • 题意
          • 分析过程
          • 给出题解

—>XJOI奋斗群(蒻蒟群)群赛17<— RANK排名9

T1:Increasing Sequence(TLE一次AC)

题意:

给你一个数列,然后给出你一个数d,数列中的每个数都可以加上d,问你最少加上几次d,能够使这个数列变成一个增序序列。

分析过程:

只要每碰到一个数比前一个数小,就加上一定的值直到大于前一个数,最后输出次数就行了。

给出题解:
#include<bits/stdc++.h>using namespace std;int main(){    int n,d;    int a[5000];    scanf("%d%d",&n,&d);    for(int i=1;i<=n;i++)    {        scanf("%d",&a[i]);    }    long long  cnt=0;    for(int i=2;i<=n;i++)    {        if(a[i]<=a[i-1])        {            int dif=a[i-1]-a[i];            dif/=d;            dif++;            a[i]+=d*dif;            cnt+=dif;        }        else continue;    }    printf("%d\n",cnt);    return 0;}

T2:Jumping Jack(WA一次后AC)

题意:

一个人在练习跳跃,第一次只能跳一个单位,之后每一次跳就能够比前一次长一个单位,问你经过多少次跳跃之后能够准确地到达x这个位置。

分析过程:

由于x的值可能是正的也可能是负的,所以要先把x取绝对值。先预估sqrt(2*x)的值作为cnt的预估值,然后再从这个值开始向答案推进。

给出题解:
#include<bits/stdc++.h>using namespace std;int main(){    int x;    scanf("%d",&x);    x=abs(x);    int cnt=sqrt(2*x);    while(cnt*(cnt+1)/2<x||(cnt*(cnt+1)/2-x)&1)    cnt++;    printf("%d\n",cnt);    return 0;}

T3:How Many Squares? (已AC)

题意:

给你一个矩阵,问你其中有几个正方形,要求正方形旁边不能有多与的边。

分析过程:

先便利每个数组中的

给出题解:
#include<bits/stdc++.h>using namespace std;int dic[8][2]= {{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};char a[255][255];int len=0;int n,m;void judge(int x,int y){    if(x<0||x>=n||y<0||y>=m||a[x][y]!='1')return ;    a[x][y]='2';    len++;    for(int i=0; i<8; i++)    {        judge(x+dic[i][0],y+dic[i][1]);    }}bool solve(int x,int y,int len,int l,int r){    for(int i=0; i<len+1; i++)        for(int j=l; j<r; j++)        {            if(x+dic[j][0]*i<0||x+dic[j][0]*i>=n||y+dic[j][1]*i<0||y+dic[j][1]*i>=m||a[x+dic[j][0]*i][y+dic[j][1]*i]!='2')                return 0;        }    return 1;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        for(int i=0; i<n; i++)            scanf("%s",a[i]);        int res=0;        for(int i=0; i<n; i++)            for(int j=0; j<m; j++)            {                if(a[i][j]=='1')                {                    len=0;                    judge(i,j);                    if(len%4)continue;                    res+=solve(i,j,len/4,0,2)&&solve(i+len/4,j+len/4,len/4,2,4);                    res+=solve(i,j,len/4,4,6)&&solve(i+len/2,j,len/4,6,8);                }            }        printf("%d\n",res);    }    return 0;}

T4:A Simple Task(WA两次之后AC)

题意:

给你一个简单的无向图,让你统计其中环的个数。

分析过程:

我们设计一个状态{[s][SET][i]}来记录起点s到终点i的简单路径的条数,其中SET表示经过的节点的集合。但由于圆排列的性质,这样的状态是有重复的。我们通过指定起点为SET中的最小序号点来消除圆排列带来的重复,状态变为{[SET][i]}。还要注意,即使这样定义状态,计算简单环个数的时候仍会将2个节点一条单边的情况当成环,也会将长度大于2的环正向计算一遍,反向计算一遍。所以我们还要进行后处理。

前向的状态转移方程可以写作:
dp[SET][j]=∑(i∈SET,i−j)dp[SET][i]
但这样的方程并不利于统计简单环的个数。

后向的状态转移方程可以写作:
设简单环的个数用统计量cnt表示。对于dp[SET][i]状态,i的每一条边eij,j∈neighbor(i):若j∈SET则说明遇到了环,dp[SET][i]贡献给cnt;若j∉SET则说明获得一条简单路径,dp[SET][i]贡献给dp[SET′][j]。

后处理:
由于长度为2的简单环被统计了进去,所以cnt−m;又由于长度大于2的简单环被统计了2遍,所以(cnt−m)/2。
最后要注意环的个数可能会达到19!个,所以我们需要用int64(之前被这个卡了好久)。

给出题解:
#include<bits/stdc++.h>using namespace std;typedef long long ll;ll n,m,ans,tot;ll tmap[20][20],f[1<<19][19];ll get_p(int a){    for(int i=0; i<n; i++)    {        if(a&(1<<i)) return i;    }}ll solve(){    ll i,j,k,p,s;    ans=0;    tot=(1<<n)-1;    memset(f,0,sizeof f);    for(i=0; i<n; i++)    {//      printf("%d %d\n",1<<i,i);        f[1<<i][i]=1;    }    for(i=1; i<=tot; i++)    {        for(j=0; j<n; j++)        {            if(f[i][j]==0) continue ;            p=get_p(i);            for(k=p; k<n; k++)            {                if(j==k) continue ;                if(tmap[j][k]==0)continue;                if(i&(1<<k))                {                    if(k==p) ans+=f[i][j];                }                else                {                    s=i|(1<<k);                    f[s][k]+=f[i][j];                }            }        }    }    ans-=m;    ans/=2;    return ans;}int main(){    scanf("%I64d%I64d",&n,&m);    memset(tmap,0,sizeof tmap);    ll u,v;    for(int i=1; i<=m; i++)    {        scanf("%I64d%I64d",&u,&v);        tmap[u-1][v-1]=tmap[v-1][u-1]=1;    }    ll res=solve();    printf("%I64d\n",res);    return 0;}}

T5:

题意:
分析过程:
给出题解:
原创粉丝点击