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时的总方案数
#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 ]都是相等的
而对于,根据转移方程,我们可以得到:
因此可以得到:
而由于第一个数为1,因此f[ 2 ][ 1 ]的初值为0,导致它会与其他数不同,但计算方法是相同的:
#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;
}