暂时只写了每题的题解,有待补充
1.「Codeforces Round #441」 Classroom Watch
【问题描述】
给出一个正整数 n,现在问存在多少个 x,使得 x在十进制下的每一位之和加上 x 等于 n。
这题拿到时就想,如果n是两位数,那么x基本上也得是两位数了,然后就觉得对于每个n的x都应有一个范围,再一想,各位数之和最多81,那么就n-81到n都试一试就好了
#include<bits/stdc++.h>
using namespace std;
int x,m=0,k,ans[10000],t,s;
int main()
{
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
scanf("%d",&x);
if(x>81)k=x-81;
else k=1;
for(int i=k;i<=x;i++)
{
t=i,s=i;
while(t>0)
{
s+=t%10;
t/=10;
if(t==0&&s==x)ans[++m]=i;
}
}
if(m!=0){
printf("%d\n",m);
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
else printf("%d\n",0);
return 0;
}
2、组合技能
蓝月商城出新技能书了!!
如果古天乐想购买“旋风斩”,则他需要花费A元;如果古天乐想买“半月弯刀”,则需要B元;如果古天乐两个一起买,则需要C元。
蓝月的设计师非常有头脑,每样商品的利润都是相同的。即假设旋风斩和半月弯刀的成本为a,b元,则A-a=B-b=C-a-b。
给出A,B,C求出利润,数据保证为正数。
已在代码中写了如何推导
#include<bits/stdc++.h>
using namespace std;
int T,A,B,C;
/*
A-a=C-a-b
b=C-A
B-b=B-C+A
*/
int main()
{
freopen("combo.in","r",stdin);
freopen("combo.out","w",stdout);
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
scanf("%d%d%d",&A,&B,&C);
printf("%d\n",B-C+A);
}
return 0;
}
3表面积
古天乐在搭积木,积木图可以抽象为一个n*m的网格图,其中第(i,j)的位置有A[i][j]个积木。求表面积。
这题得注意凹在里面的也算表面积
不过可以算出总面积和重叠的面积,再相减,思路在注释中已注明
#include<bits/stdc++.h>
using namespace std;
int n,m,sum1=0,sum2,a[110][110]={};
int main()
{
freopen("surface.in","r",stdin);
freopen("surface.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
sum1+=a[i][j];
//对于每一个位置,计算上面,左边,以及自己的重叠
//因为 是从左上枚举到右下,所以每次把左边上面的算出就好了
sum2+=min(a[i][j],a[i-1][j])+min(a[i][j],a[i][j-1])+(a[i][j]-1);
// 自己或左边 上面或自己 每一格有(a[i][j]-1)个重叠位置
}
printf("%d\n",sum1*6-sum2*2);
return 0;
}
4红皇后的旅行
给定一个n*n的棋盘,行和列标号为0,1,2,….,n-1。在棋盘的(i_start,j_start)位置上有一位红皇后,每次红皇后可以往六个方向走,如图所示:
现在红皇后想去(i_end,j_end)点,求最短距离,并且输出一条路径。
显然最短路径有无穷条,请按照以下顺序来搜索:UL, UR, R, LR, LL, L。
如果无解,输出Impossible
这题就先用BFS求出最短路,并记录每格的上一格,再用DFS求出路径
#include<bits/stdc++.h>
using namespace std;
int n,d[210][210];
struct K{int x,y;};
K start,end,v[210][210];
queue<K>q;
string D[6]={"UL","UR","R","LR","LL","L"};
int dx[6]={-2,-2,0,2,2,0},dy[6]={-1,1,2,1,-1,-2};
/*
d[i][j]表示走到(i,j)的最小距离
v[i][j]表示走到(i,j)的上一个位置
*/
void BFS()
{
memset(d,-1,sizeof(d));
memset(v,-1,sizeof(v));
while(!q.empty())q.pop();
q.push(start);
d[start.x][start.y]=0;
while(!q.empty())
{
K now=q.front();
q.pop();
for(int i=0;i<6;i++)//向六个方向走
{
K k;
int xx=now.x+dx[i],yy=now.y+dy[i];//新的位置
if(d[xx][yy]!=-1||xx<0||xx>n||yy<0||yy>n)//位置越界或者已走到
continue;
k.x=xx,k.y=yy;
q.push(k);
d[xx][yy]=d[now.x][now.y]+1;
v[xx][yy].x=now.x,v[xx][yy].y=now.y;
if(xx==end.x&&yy==end.y)return;
}
}
cout<<"Impossible"<<endl;
exit(0);
}
void DFS(K now)
{
int xx=now.x,yy=now.y;
int xb=v[now.x][now.y].x;
int yb=v[now.x][now.y].y;
if(xb==-1&&yb==-1)return ;
DFS(v[now.x][now.y]);
for(int i=0;i<6;i++)
if(xb+dx[i]==xx&&yb+dy[i]==yy)
{
cout<<D[i]<<' ';
break;
}
}
int main()
{
freopen("redqueen.in","r",stdin);
freopen("redqueen.out","w",stdout);
scanf("%d%d%d%d%d",&n,&start.x,&start.y,&end.x,&end.y);
BFS();
printf("%d\n",d[end.x][end.y]);
DFS(end);
return 0;
}
5构造序列
有一个长度为n的序列A,其中A[1]=1,A[n]=x,A[2…n-1]可以是1至k间任意一个正整数。求有多少个不同的序列,使得相邻两个数不同。
答案对10^9+7取模。
#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
long long n,k,x,f[100100],fx[100100];
int main()
{
freopen("construct.in","r",stdin);
freopen("construct.out","w",stdout);
scanf("%d%d%d",&n,&k,&x);
f[2]=k-1;
for(int i=3;i<n;i++)
f[i]=(f[i-1]*(k-1))%mod;
if(x==1)fx[2]=0;
else fx[2]=1;
for(int i=3;i<=n;i++)
fx[i]=(f[i-1]-fx[i-1]+mod)%mod;
cout<<fx[n]<<endl;
return 0;
}