给你一个数列,然后给出你一个数d,数列中的每个数都可以加上d,问你最少加上几次d,能够使这个数列变成一个增序序列。
只要每碰到一个数比前一个数小,就加上一定的值直到大于前一个数,最后输出次数就行了。
#include
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;
}
一个人在练习跳跃,第一次只能跳一个单位,之后每一次跳就能够比前一次长一个单位,问你经过多少次跳跃之后能够准确地到达x这个位置。
由于x的值可能是正的也可能是负的,所以要先把x取绝对值。先预估sqrt(2*x)的值作为cnt的预估值,然后再从这个值开始向答案推进。
#include
using namespace std;
int main()
{
int x;
scanf("%d",&x);
x=abs(x);
int cnt=sqrt(2*x);
while(cnt*(cnt+1)/21)/2-x)&1)
cnt++;
printf("%d\n",cnt);
return 0;
}
给你一个矩阵,问你其中有几个正方形,要求正方形旁边不能有多与的边。
先便利每个数组中的
#include
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; i1; i++)
for(int j=l; jif(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"%s",a[i]);
int res=0;
for(int i=0; ifor(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;
}
给你一个简单的无向图,让你统计其中环的个数。
我们设计一个状态{[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
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; iif(a&(1<return i;
}
}
ll solve()
{
ll i,j,k,p,s;
ans=0;
tot=(1<1;
memset(f,0,sizeof f);
for(i=0; i// printf("%d %d\n",1<
f[1<1;
}
for(i=1; i<=tot; i++)
{
for(j=0; jif(f[i][j]==0) continue ;
p=get_p(i);
for(k=p; kif(j==k) continue ;
if(tmap[j][k]==0)continue;
if(i&(1<if(k==p) ans+=f[i][j];
}
else
{
s=i|(1<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;
}
}