这一次也说不出考的好不好,好嘛,最后一题没有AC(推了两个小时的组合数学,1个小时在对拍,可以说是最有把握的一题)不好嘛,前4道A了,所以也说不出什么,算了,不说了。
我拿到了试卷,首先,先看了T1,没看出来,我就看了T2,一看我就知道怎么做了,所以我5,6分钟就写好了代码,之后我看了一下T3,发现我会做,但是太麻烦,我就放了放。看了T4,我想这一道题就输出方案占时不会,估计做的时候就会了(因为最近都在写一些要输出方案的DP,不会也得会啊),我去看T5,看了两分钟,我就放弃了。
然后我去做T3,做到了一半,发现自己好像会做了T1,我就把T3甩开,去做T1,做完了我又去做T3,不一会也就把T3做完了,之后我又去做T4,输出答案后,我又想到怎么输出方案,很快也就写完了。这里总共用时不超过70分钟。
接下来我就开始我艰苦的历程,首先,我推T4先推了30分钟推出来了一个答案之后,我试了几个数,发现不对,我意识到这有可能要推很久,为了方便,我写了一个对拍,也很快就推好了,然后我又写了60分钟,对拍的程序和我的程序没问题了,我就放在那对拍了1个小时(没有任何错误)之后我就在检查前面的题,做后就是这样的成绩
现在分析一下题目
1.「Codeforces Round #441」 Classroom Watch
(num.pas/c/cpp)
【问题描述】
给出一个正整数 n,现在问存在多少个 x,使得 x在十进制下的每一位之和加上 x 等于 n。
【输入】
共 1 行,一个正整数n 。
【输出】
第一行输出一个整数 m,表示有 m 个符合条件的 (若没有符合条件的 ,请只输出一个 0)。
下面m行,每行一个 x ,x按从小到大输出。
【输入输出样例1】
num.in | num.out |
21 | |
【数据范围】
这一题,没有什么理由,就是想到了就完事了,我们发现这里有每个数之和,枚举一下所有数之和,再用n减一下判断是否合法就行了
代码
#include<bits/stdc++.h>
using namespace std;
int U(int x)
{
int sum=0;
while(x>0)
{
sum+=x%10;
x/=10;
}
return sum;
}
int a[100],tot,n;
int main()
{
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
scanf("%d",&n);
for(int i=0;i<=81;i++)if(U(n-i)==i)a[++tot]=n-i;
sort(a+1,a+tot+1);
printf("%d\n",tot);
for(int i=1;i<=tot;i++)
printf("%d\n",a[i]);
return 0;
}
组合技能(combo.cpp)
题目描述
蓝月商城出新技能书了!!
如果古天乐想购买“旋风斩”,则他需要花费A元;如果古天乐想买“半月弯刀”,则需要B元;如果古天乐两个一起买,则需要C元。
蓝月的设计师非常有头脑,每样商品的利润都是相同的。即假设旋风斩和半月弯刀的成本为a,b元,则A-a=B-b=C-a-b。
给出A,B,C求出利润,数据保证为正数。
格式
输入第一行一个数T,表示T次询问。
接下来T行,每行三个数A,B,C
输出T行,每行一个数,表示利润。
范围
T <= 100
A,B,C <= 2000
Sample Input 0
3
275 214 420
6 9 11
199 199 255
Sample Output 0
69
4
143
这一题很容易看出来,答案就是A+B-C不用讲
表面积(surface.cpp)
题目描述
古天乐在搭积木,积木图可以抽象为一个n*m的网格图,其中第(i,j)的位置有A[i][j]个积木。求表面积。
格式
输入第一行两个数n,m,接下来n行每行m个数,表示A[i][j]。
输出一个数,表示表面积。
范围
Sample Input 0
1 1
1
Sample Output 0
6
Sample Input 1
3 3
1 3 4
2 2 3
1 2 4
Sample Output 1
60
这一题是一道模拟题,不难,你只要从一个点的上下左右看就行(前后都是1,不用看)
代码:
#include<bits/stdc++.h>
using namespace std;
int read()
{
int num=0;bool flag=1;
char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-')flag=0;
for(;c>='0'&&c<='9';c=getchar())
num=(num<<1)+(num<<3)+c-'0';
return flag?num:-num;
}
int n,m,a[110][110];
int main()
{
freopen("surface.in","r",stdin);
freopen("surface.out","w",stdout);
n=read();m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]=read();
int sum=2*n*m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
sum=sum+max(0,a[i][j]-a[i-1][j]);
sum=sum+max(0,a[i][j]-a[i][j-1]);
sum=sum+max(0,a[i][j]-a[i+1][j]);
sum=sum+max(0,a[i][j]-a[i][j+1]);
}
cout<<sum;
return 0;
}
红皇后的旅行(redqueen.cpp)
题目描述
给定一个n*n的棋盘,行和列标号为0,1,2,….,n-1。在棋盘的(i_start,j_start)位置上有一位红皇后,每次红皇后可以往六个方向走,如图所示:
现在红皇后想去(i_end,j_end)点,求最短距离,并且输出一条路径。
显然最短路径有无穷条,请按照以下顺序来搜索:UL, UR, R, LR, LL, L。
如果无解,输出Impossible
格式
输入第一行一个数n,第二行四个数,i_start,j_start,i_end,j_end。
输出第一行一个数,最小步数,第二行输出方案。
范围
Sample Input 0
7
6 6 0 1
Sample Output 0
4
UL UL UL L
Sample Input 1
6
5 1 0 5
Sample Output 1
Impossible
Sample Input 2
7
0 3 4 3
Sample Output 2
2
LR LL
这一道毫无疑问,是一道BFS,没问题对吧,主要是一个方案输出,但是经过了这么多次的练习,方案输出都已经不是问题了,只要我们用一个v[xx][yy](pair或者结构体)来储存一下这一状态是从那一状态转移过来的就行了,之后再dfs从尾查找就行。
代码:
#include<bits/stdc++.h>
using namespace std;
struct cow{int x,y;};
queue<cow>q;int n,d[210][210];cow st,ed,v[210][210];
int dx[6]={-2,-2,+0,+2,+2,+0},dy[6]={-1,+1,+2,+1,-1,-2};
string D[6]={"UL","UR","R","LR","LL","L"};
void BFS()
{
memset(d,-1,sizeof(d));
memset(v,-1,sizeof(v));
while(!q.empty())q.pop();
q.push(st);d[st.x][st.y]=0;
while(!q.empty())
{
cow now=q.front();q.pop();
for(int i=0;i<6;i++)
{
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;
q.push(cow{xx,yy});
d[xx][yy]=d[now.x][now.y]+1;
v[xx][yy].x=now.x;v[xx][yy].y=now.y;
if(xx==ed.x&&yy==ed.y)return ;
}
}
cout<<"Impossible";exit(0);
}
void dfs(cow 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,&st.x,&st.y,&ed.x,&ed.y);
BFS();printf("%d\n",d[ed.x][ed.y]);dfs(ed);
return 0;
}
构造序列(construct.cpp)
题目描述
有一个长度为n的序列A,其中A[1]=1,A[n]=x,A[2…n-1]可以是1至k间任意一个正整数。求有多少个不同的序列,使得相邻两个数不同。
答案对10^9+7取模。
格式
输入共一行,包含三个数,n,k,x。
输出一个数,表示答案。
范围
Sample Input 1
4 3 2
Sample Output 1
3
这道题我一看:一定要用快速幂!然后我之后就没有想到正解,真的很崩溃。现在来说一下正解
先考虑如果没有A[1]和A[n]的限制,怎么办?答案就是k*(k-1)^(n-1)
如果只有A[1]的限制?答案就是(k-1)^(n-1)
这样我们就可以知道一个很神奇的正解:
f[i]表示i这个位置为x是的方案数
f[i]=(k-1)^(i-2)-f[i-1] 最后输出f[n]即可
代码:
#include<bits/stdc++.h>
using namespace std;
#define Mod 1000000007
#define ll long long
ll pow(ll x,ll y)
{
if(y==0)return 0;
ll sum=pow(x,y/2);
sum=(sum*2)%Mod;
if(y&1)return (sum+x)%Mod;
return sum;
}
ll power(ll x,ll y)
{
if(y==0)return 1;
ll sum=power(x,y/2)%Mod;
if(y&1)return pow(pow(sum,sum),x)%Mod;
return pow(sum,sum)%Mod;
}
int f[100010];
int main()
{
freopen("construct.in","r",stdin);
freopen("construct.out","w",stdout);
int n,k,x;cin>>n>>k>>x;
if(x==1)f[2]=0;else f[2]=1;
for(int i=3;i<=n;i++)
f[i]=(power(k-1,i-2)-f[i-1]+Mod)%Mod;
cout<<f[n];
return 0;
}