1312:【例3.4】昆虫繁殖
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 4463 通过数: 2077
【题目描述】
科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强。每对成虫过x个月产y对卵,每对卵要过两个月长成成虫。假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过X个月产卵),问过Z个月以后,共有成虫多少对?0≤X≤20,1≤Y≤20,X≤Z≤50。
【输入】
x,y,z的数值。
【输出】
过Z个月以后,共有成虫对数。
【输入样例】
1 2 8
【输出样例】
37
思路:
ps这个题好难懂啊,样例都看不懂qwq
对与样例,就是成虫此时在第0天,它第2,4,6,8天的时候会产卵,然后第2天的卵在第4天,变成成虫,然后在第5天可以产卵。
设a[i]表示第i天成虫的数量
具体见注释
代码如下:
#include<iostream>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int INF=0x3f3f3f3f;
const int N=105;
ll a[N];
int main(){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
for(int i=0;i<x+2;i++)a[i]=1;
//第1只成虫在第x天产地1批卵,卵在x+2天变成成虫
//在此期间成虫数量都是1
for(int i=x+2;i<=z;i++){
a[i]=a[i-1]+a[i-x-2]*y;
//第i天的成虫数量等于i-1天的成虫数量+第i天从卵变成成虫的数量
//卵变成的成虫,在第i-2天的时候被孵化,其数量等于i-2-x天成虫数量*y
}
printf("%lld\n",a[z]);
}
1313:【例3.5】位数问题
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 3018 通过数: 1539
【题目描述】
在所有的N位数中,有多少个数中有偶数个数字3?由于结果可能很大,你只需要输出这个答案对12345取余的值。
【输入】
读入一个数N。
【输出】
输出有多少个数中有偶数个数字3。
【输入样例】
2
【输出样例】
73
思路:
设ji[i]表示i位数中有奇数个3的个数(位数是从右往左算)
ou[i]表示i位数中有偶数个3的个数
hin明显ji[1]=1(只有3)ou[1]=9
递推方程:
ou[i]=ji[i-1]+ou[i-1]*9(若i是最高位则*8,因为0不能开头)
ji[i]=ou[i-1]+ji[i-1]*9(若i是最高位则*8,因为0不能开头)
代码如下:
#include<iostream>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int INF=0x3f3f3f3f,mod=12345;
const int N=1005;
ll ou[N],ji[N];//ou[i]表示第i为有偶数个3的个数,ji表示第i为有奇数个3的个数
int main(){
int n;
while(scanf("%d",&n)!=EOF){
ou[1]=9;ji[1]=1;
int x=9;
for(int i=2;i<=n;i++){
if(i==n)x=8;
ou[i]=(ou[i-1]*x%mod+ji[i-1])%mod;
ji[i]=(ji[i-1]*x%mod+ou[i-1])%mod;
}
printf("%lld\n",ou[n]%mod);
}
}
1314:【例3.6】过河卒(Noip2002)
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 3400 通过数: 1359
【题目描述】
棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的某一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,……,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,C≠A且C≠B。现在要求你计算出卒从A点能够到达B点的路径的条数。
【输入】
给出n、m和C点的坐标。
【输出】
从A点能够到达B点的路径的条数。
【输入样例】
8 6 0 4
【输出样例】
1617
思路:
递推公式:dp[i][j]=dp[i-1][j]+dp[i][j-1];
正常情况下,我们这样初始化:
for(int i=1;i<=max(n,m);i++){
dp[i][0]=1;
dp[0][i]=1;
}
dp[0][0]=0;
但是,这题里有我们不能到达的点,那么第0行,第0列这列点后的点都不可达!
还有就是找这些不可达点的时候注意不要数组越界哦~
代码如下:
#include<iostream>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int INF=0x3f3f3f3f,mod=12345;
const int N=25;
ll dp[N][N],yes[N][N];
void init(int x,int y){
yes[x][y]=1;
if(x-1>=0){
yes[x-1][y+2]=1;
if(y-2>=0)yes[x-1][y-2]=1;
}
if(x-2>=0){
yes[x-2][y+1]=1;
if(y-1>=0)yes[x-2][y-1]=1;
}
if(y-1>=0){
yes[x+2][y-1]=1;
}
if(y-2>=0){
yes[x+1][y-2]=1;
}
yes[x+1][y+2]=1;
yes[x+2][y+1]=1;
}
int main(){
int n,m,x,y;
scanf("%d%d%d%d",&n,&m,&x,&y);
init(x,y);
dp[0][0]=0;
for(int i=1;i<=n;i++){
if(yes[i][0]){dp[i][0]=0;break;}
else dp[i][0]=1;
}
for(int i=1;i<=m;i++){
if(yes[0][i]){dp[0][i]=0;break;}
else dp[0][i]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(yes[i][j])dp[i][j]=0;
else {
dp[i][j]=dp[i][j-1]+dp[i-1][j];
}
}
}
printf("%lld\n",dp[n][m]);
}