发表在 手把手教你C++ 09-03 09:13:38
以下解法全是我的弱鸡解法,请大神指点!!!
题目就不细读了
第一题
思路:用下标从0到10的数组来存,每个元素i表示i岁的兔子有几只
先说60分做法:纯纯的模拟!!!
循环n年,每年做这些事:
1.符合生育要求的兔子就生宝宝(注意,宝宝要放到a[0]里面,代表0岁)
2.每只兔子,出刚生下来的外,年龄增加!
3.到了10岁的兔子,就让a[10]=0,做清零处理
最后统计一共几只兔子
搞定!
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define MOD 1000000007
using namespace std;
int main()
{
freopen("d2t1.in","r",stdin);
freopen("d2t1.out","w",stdout);
int num,ans=0;
int rabit[11]={0};
rabit[1]=1;
scanf("%d",&num);
for(int i=1;i<=num;i++)
{
for(int j=2;j<=10;j++)
rabit[0]=(rabit[0]+rabit[j])%MOD;
for(int j=10;j>=1;j--)
rabit[j]=rabit[j-1];
rabit[0]=0;
}
for(int i=1;i<=10;i++)
ans=(ans+rabit[i])%MOD;
printf("%d",ans);
return 0;
}
满分解法:矩阵乘法+快速幂
用二维来存兔子,然后矩阵乘法,对结果进行快速幂,即可求得结果
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
const int mod=1000000007;
using namespace std;
long long n,c[11][11]={
{1,0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,0,0},
{0,0,0,0,1,0,0,0,0,0,0},
{0,0,0,0,0,1,0,0,0,0,0},
{0,0,0,0,0,0,1,0,0,0,0},
{0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,1,0,0},
{0,0,0,0,0,0,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,0,1}
};
long long b[11][11]={
{0,1,0,0,0,0,0,0,0,0,0},
{1,0,1,0,0,0,0,0,0,0,0},
{1,0,0,1,0,0,0,0,0,0,0},
{1,0,0,0,1,0,0,0,0,0,0},
{1,0,0,0,0,1,0,0,0,0,0},
{1,0,0,0,0,0,1,0,0,0,0},
{1,0,0,0,0,0,0,1,0,0,0},
{1,0,0,0,0,0,0,0,1,0,0},
{1,0,0,0,0,0,0,0,0,1,0},
{1,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,0,0,0}
};
long long ans;
struct mtx
{
long long a[11][11];
mtx()
{
for(long long i=0;i<=10;i++)
for(long long j=0;j<=10;j++)
a[i][j]=0;
}
mtx(long long b[11][11])
{
for(long long i=0;i<=10;i++)
for(long long j=0;j<=10;j++)
a[i][j]=b[i][j];
}
mtx operator * (mtx b)
{
mtx ans;
for(long long i=0;i<=10;i++)
for(long long j=0;j<=10;j++)
for(long long k=0;k<=10;k++)
ans.a[i][j]=(ans.a[i][j]+(a[i][k]*b.a[k][j])%mod)%mod;
return ans;
}
}mtr_ans,mtr_spc;
int main()
{
freopen("d2t1.in","r",stdin);
freopen("d2t1.out","w",stdout);
mtr_ans=mtx(c);mtr_spc=mtx(b);
scanf("%lld",&n);
while(n)
{
if(n&1)mtr_ans=mtr_ans*mtr_spc;
mtr_spc=mtr_spc*mtr_spc;
n>>=1;
}
for(long long i=0;i<=10;i++)
ans=(ans+mtr_ans.a[0][i])%mod;
printf("%lld\n",ans);
return 0;
}
第二题:
60分做法:
对读入的数据进行处理,不用再开一个循环了,然后模拟冒泡排序(冒几次,统计几次),最后输出。
代码如下:(冒泡部分优化
#include<iostream>
#include<cmath>
using namespace std;
const int MAX=100001;
int main()
{
freopen("d2t2.in","r",stdin);
freopen("d2t2.out","w",stdout);
int num;
int a[MAX]={0};
scanf("%d",&num);
for(int i=1;i<=num;i++)
scanf("%d",&a[i]);
scanf("%d",&num);
for(int n=1;n<=num;n++)
{
int begin,end;
scanf("%d %d",&begin,&end);
int b[MAX]={0},tum=1;
for(int i=begin;i<=end;i++)
{
b[tum++]=a[i];
} tum--;
int ans=0;
int i=1;
bool flag;
do
{
flag=true;
for(int j=1;j<=tum-i;j++)
if(b[j]>b[j+1])
{
int tmp;
tmp=b[j];
b[j]=b[j+1];
b[j+1]=tmp;
flag=false;
ans++;
}
i++;
}while(!flag);
/*
for(int i=1;i<=tum-1;i++)
for(int j=1;j<=tum-i;j++)
{
if(b[j]>b[j+1])
{
int tmp;
tmp=b[j];
b[j]=b[j+1];
b[j+1]=tmp;
ans++;
}
}*/
printf("%d\n",ans);
}
return 0;
})
满分解法:莫队+树状数组
思路:数学证明,可得出转移思路!!!
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long maxn=30000+10;
long long bit[maxn],ar[maxn],n,m;
long long lowbit(long long k){return k&-k;}
void update(long long k,long long a)
{
while(k<=n)
{
bit[k]+=a;
k+=lowbit(k);
}
}
long long query(long long k)
{
long long sum=0;
while(k>0)
{
sum+=bit[k];
k-=k&-k;
}
return sum;
}
int main()
{
freopen("d2t2.in","r",stdin);
freopen("d2t2.out","w",stdout);
scanf("%lld",&n);
for(long long i=1;i<=n;i++)
scanf("%lld",&ar[i]);
memset(bit,0,sizeof(bit));
scanf("%lld",&m);
long long sum=0;
long long lp=1,rp=1;
update(ar[1],1);
for(long long i=1;i<=m;i++)
{
long long l,r;
scanf("%lld%lld",&l,&r);
while(lp<l)
{
update(ar[lp],-1);
sum-=query(ar[lp]-1);
lp++;
}
while(lp>l)
{
lp--;
sum+=query(ar[lp]-1);
update(ar[lp],1);
}
while(rp<r)
{
rp++;
sum+=query(n)-query(ar[rp]);
update(ar[rp],1);
}
while(rp>r)
{
update(ar[rp],-1);
sum-=query(n)-query(ar[rp]);
rp--;
}
printf("%lld\n",sum);
}
return 0;
}
第三题:
——用三进制表示村民状态
先看数据:
救一个人得10分,不要白不要!!!
用搜索得20,代码就不讲了
60分解法:广搜
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,k,map[11][11],tim[11],num=0;
struct data
{
int x,y,step;
}h[11],s,t;
char a[11];
int bfs(data from,data to,int v)
{
queue<data> q;
bool vis[11][11]={{0},{0}};
int mx[5]={0},my[5]={0};
mx[1]=1;
mx[2]=-1;
my[3]=1;
my[4]=-1;
from.step=0;
vis[from.x][from.y]=1;
q.push(from);
while(!q.empty())
{
data u=q.front();
q.pop();
if(u.x==to.x&&u.y==to.y)
{
if(v>1)
return u.step*v;
else
return u.step;
}
for(int i=1;i<=4;i++)
{
data g=u;
g.step++;
g.x+=mx[i];
g.y+=my[i];
if(g.x<1||g.x>n||g.y<1||g.y>n)
continue;
if(map[g.x][g.y])
continue;
if(vis[g.x][g.y])
continue;
q.push(g);
}
}
return 0;
}
int main()
{
freopen("d2t3.in","r",stdin);
freopen("d2t3.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%s",a);
for(int j=0;j<m;j++)
{
if(a[j]=='.') continue;
if(a[j]=='#')
{
map[i][j+1]=1;
continue;
}
if(a[j]=='s')
{
s.x=i;
s.y=j+1;
continue;
}
if(a[j]=='t')
{
t.x=i;
t.y=j+1;
continue;
}
if(a[j]>='A'&&a[j]<='Z')
{
num++;
h[a[j]-'A'+1].x=i;
h[a[j]-'A'+1].y=j+1;
continue;
}
}
}
for(int i=1;i<=num;i++)
{
int temp;
scanf("%s%d",a,&temp);
tim[a[0]-'A'+1]=temp;
}
int odr[11],mint=9999999;
for(int i=1;i<=n;i++)
odr[i]=i;
do
{
int ans=0,v=k;
ans+=bfs(s,h[odr[1]],v);
if(ans>mint)
continue;
v=v+tim[odr[1]];
for(int i=1;i<num;i++)
{
ans+=bfs(h[odr[i]],h[odr[i+1]],v);
v=v+tim[odr[i+1]];
if(ans>mint)
continue;
}
ans+=bfs(h[odr[num]],t,v);
mint=min(mint,ans);
}while(next_permutation(odr+1,odr+1+num));
printf("%d",mint);
return 0;
}
满分解法:
听说用dp,但是,还是小白的我,只会对付高中生的dp啊!!!
所以,代码木有,不会写,想看的可以上网搜!!!
嘿嘿柯的分数是260分,有没有大神超过了呢?
有点话,请在评论区自豪地发言!!!
怎么样,简单吧,轻轻松松上200分!!!
有异议的在评论区留言哦~
大神
把题目拿过来呀
大神,我……看不懂