5.31考试

 

 

Classroom Watch

给出一个正整数n(n<=10^9),求有多少个k满足k在十进制下的各位数字之和加上k等于n

input

21

output

1

15

 

乍一眼还以为是数论题,但因为各位数字之和不超过9*9,只要在n-9*9到n之间暴力枚举就行了

#include<bits/stdc++.h>
using namespace std;
int a[1010],n,k,s,ans;
int main()
{
	scanf("%d",&n);
	for(int i=max(n-9*9,0);i<=n;i++)
	 {
	   k=i; s=0;
	   while(k!=0)
	    {
	      s+=k%10;
	      k/=10;
		}
	   if(i+s==n) 
	    {
	      ans++;
	      a[ans]=i;
		}
	 }
	if(ans==0) printf("0\n");
	else printf("%d\n",ans);
	for(int i=1;i<=ans;i++)
	  printf("%d\n",a[i]);
	return 0;
}

 

combo

两件商品价格分别为A元和B元,同时购买两件需要C元

购买商品的利润全都相同,若两件商品的成本分别为a元和b元

则:A-a=B-b=C-a-b

现给出A,B,C,求利润

input

3
275 214 420
6 9 11
199 199 255

 

易证,利润=A+B-C

#include<bits/stdc++.h>
using namespace std;
int n,x,y,z;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	 {
	   scanf("%d%d%d",&x,&y,&z);
	   printf("%d\n",x+y-z);
	 }
	return 0;
} 

 

surface

一个n*m的网格图,第i行第j列有a[ i ] [ j ]个积木,求所有积木的表面积之和

input1

1 1
1

output1

6

input2

3 3

1 3 4 

2 2 3 

1 2 4

 

对于每个位置的积木,若周围没有其他积木,则表面积为a[ i ][ j ]*4+2;

若a[ i-1 ][ j ]不为0,则会遮去min(a[ i-1 ][ j ],a[ i ][ j ])面积的积木,a[ i+1 ][ j ],a[ i ][ j-1 ],a[ i ][ j+1 ]同理

#include<bits/stdc++.h>
using namespace std;
int a[110][110],n,m,ans;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=m;j++)
	    scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=m;j++)
	    ans+=a[i][j]*4+2-min(a[i-1][j],a[i][j])-min(a[i+1][j],a[i][j])-min(a[i][j-1],a[i][j])-min(a[i][j+1],a[i][j]);
	printf("%d\n",ans);
	return 0;
}

 

redqueen

给定一个n*n的棋盘,行和列标号为0,1,2,….,n-1。在棋盘的(i_start,j_start)位置上有一位红皇后,每次红皇后可以往六个方向走,如图所示:

现在红皇后想去(i_end,j_end)点,求最短距离,并且输出一条路径。

显然最短路径有无穷条,请按照以下顺序来搜索:UL, UR, R, LR, LL, L

如果无解,输出Impossible

input1

7

6 6 0 1

output1

4

UL UL UL L

input2

6

5 1 0 5

output2

Impossible

input3

7

0 3 4 3

output3

2

LR LL

 

搜索,回溯输出方案

#include<bits/stdc++.h>
using namespace std;
int qx[40010],qy[40010],la[210][210],n,h,t,i_s,j_s,i_e,j_e,ans;
bool vis[210][210];
void dfs(int x,int y)
{
	if(x==i_s&&y==j_s) 
	 {
	   printf("%d\n",ans);
	   return;
     }
	ans++;
	if(la[x][y]==1) 
	 {
	   dfs(x+2,y+1);
	   printf("UL ");
     }
	if(la[x][y]==2) 
	 {
	   dfs(x+2,y-1);
	   printf("UR ");
     }
	if(la[x][y]==3) 
	 {
	   dfs(x,y-2);
	   printf("R ");
     }
	if(la[x][y]==4) 
	 {
	   dfs(x-2,y-1);
	   printf("LR ");
     }
	if(la[x][y]==5) 
	 {
	   dfs(x-2,y+1);
	   printf("LL ");
     }
	if(la[x][y]==6) 
	 {
	   dfs(x,y+2);
	   printf("L ");
     }
}
void bfs(int x,int y)
{
	h=0; t=1;
	qx[1]=x; qy[1]=y;
	vis[x][y]=1; la[x][y]=0;
	while(h<t)
	 {
	   h++;
	   if(qx[h]>=2&&qy[h]>=1&&!vis[qx[h]-2][qy[h]-1])
	    {
	      qx[++t]=qx[h]-2;
	      qy[t]=qy[h]-1;
	      la[qx[t]][qy[t]]=1;
	      vis[qx[t]][qy[t]]=1;
		}
	   if(qx[h]>=2&&qy[h]<n-1&&!vis[qx[h]-2][qy[h]+1])
	    {
	      qx[++t]=qx[h]-2;
	      qy[t]=qy[h]+1;
	      la[qx[t]][qy[t]]=2;
	      vis[qx[t]][qy[t]]=1;
		}
	   if(qy[h]<n-2&&!vis[qx[h]][qy[h]+2])
	    {
	      qx[++t]=qx[h];
	      qy[t]=qy[h]+2;
	      la[qx[t]][qy[t]]=3;
	      vis[qx[t]][qy[t]]=1;
		}
	   if(qx[h]<n-2&&qy[h]<n-1&&!vis[qx[h]+2][qy[h]+1])
	    {
	      qx[++t]=qx[h]+2;
	      qy[t]=qy[h]+1;
	      la[qx[t]][qy[t]]=4;
	      vis[qx[t]][qy[t]]=1;
		}
	   if(qx[h]<n-2&&qy[h]>=1&&!vis[qx[h]+2][qy[h]-1])
	    {
	      qx[++t]=qx[h]+2;
	      qy[t]=qy[h]-1;
	      la[qx[t]][qy[t]]=5;
	      vis[qx[t]][qy[t]]=1;
		}
	   if(qy[h]>=2&&!vis[qx[h]][qy[h]-2])
	    {
	      qx[++t]=qx[h];
	      qy[t]=qy[h]-2;
	      la[qx[t]][qy[t]]=6;
	      vis[qx[t]][qy[t]]=1;
		}
	   if(vis[i_e][j_e])
	    {
	      dfs(i_e,j_e);
	      break;
		}
	 }
}
int main()
{
	scanf("%d%d%d%d%d",&n,&i_s,&j_s,&i_e,&j_e);
	bfs(i_s,j_s);
	if(ans==0) printf("Impossible\n"); 
	return 0;
}

construct

有一个长度为n的序列A,其中A[1]=1,A[n]=x,A[2…n-1]可以是1至k间任意一个正整数。求有多少个不同的序列,使得相邻两个数不同,答案对10^9+7取模。

input

4 3 2

output

3

 

设f[ i ][ j ]表示第i个数为j时的总方案数

f[i][j]=f[i][j]+\sum f[i-1][l](1\leq l\leq k)(l!=j)

#include<bits/stdc++.h>
using namespace std;
long long f[1010][1010],n,m,k,s,ss,ans;
int main()
{
	scanf("%lld%lld%lld",&n,&k,&m);
	for(int i=2;i<=k;i++) f[2][i]=1;
	ss=k-1;
	for(int i=3;i<n;i++)
	 {
	   s=ss; ss=0;
	   for(int j=1;j<=k;j++)
	    {
	      f[i][j]=(f[i][j]+s-f[i-1][j])%1000000007;
	      ss+=f[i][j];
	    }
	 }
	for(int i=1;i<=k;i++)
	  if(i!=m) ans=(ans+f[n-1][i])%1000000007;
	printf("%lld\n",ans);
	return 0;
}

复杂度O(nk),而且数组开不下

此时输出f数组:

#include<bits/stdc++.h>
using namespace std;
long long f[1010][1010],n,m,k,s,ss,ans;
int main()
{
	scanf("%lld%lld%lld",&n,&k,&m);
	for(int i=2;i<=k;i++) f[2][i]=1;
	ss=k-1;
	for(int i=3;i<n;i++)
	 {
	   s=ss; ss=0;
	   for(int j=1;j<=k;j++)
	    {
	      f[i][j]=(f[i][j]+s-f[i-1][j])%1000000007;
	      cout<<f[i][j]<<' ';
	      ss+=f[i][j];
	    }
	    cout<<endl;
	 }
	for(int i=1;i<=k;i++)
	  if(i!=m) ans=(ans+f[n-1][i])%1000000007;
	printf("%lld\n",ans);
	return 0;
}

结果如下:

 

我们可以发现,对于任意i,f[ i ][ 2 ]~f[ i ][ k ]都是相等的

而对于f[i+1][j](2\leq j\leq k),根据转移方程,我们可以得到:f[i+1][j]=\sum f[i][l]-f[i][j](1\leq l\leq k)

因此可以得到:f[i+1][j]=f[i][1]+f[i][2]*(k-2)(2\leq j\leq k)

而由于第一个数为1,因此f[ 2 ][ 1 ]的初值为0,导致它会与其他数不同,但计算方法是相同的:

f[i+1][1]=f[i][2]*(k-1)

#include<bits/stdc++.h>
using namespace std;
int n,m;
long long k,x,y,q,p;
int main()
{
	scanf("%d%lld%d",&n,&k,&m);
	x=1; y=0;
	for(int i=2;i<=n;i++)
	 {
	   q=x; p=y;
	   x=(p*(k-1))%1000000007;
	   y=(p*(k-2)%1000000007+q)%1000000007;
	 }
	if(m==1) printf("%lld\n",x);
	else printf("%lld\n",y);
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值