C
- 题意:爬楼梯,每次爬1~2层,有些层不能爬
- 题解:斐波那契数列(标数法)递推
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=100005;
const int mod=1e9+7;
int n,m,num[maxn];
bool flag[maxn];
int main()
{
int n,m; scanf("%d%d",&n,&m);
for(int i=1,u;i<=m;++i) scanf("%d",&u),flag[u]=1;
if(!flag[1]&&!flag[2]) {num[1]=1; num[2]=2;}
else if(flag[1]&&!flag[2]) num[2]=1;
else if(flag[1]&&flag[2]) {puts("0"); return 0;}
for(int i=3;i<=n;++i)
if(!flag[i]) num[i]=((long long)num[i-1]+num[i-2])%mod;
cout<<num[n]<<endl;
return 0;
}
D
- 题意:n*m网格中有一些障碍,你有一盏灯,放下后照亮所在行,列未被障碍物遮挡的位置
- 题解:两个数组分别统计[i][j]处放灯价值(rows,columns)数组,输出一下就知道,最后行列和求最大值
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=2005;
int n,m,lastr,lastc[maxn],rows[maxn][maxn],columns[maxn][maxn],ans;
int max(int a,int b){return a>b?a:b;}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
lastr=0; char temp=getchar();
for(int j=1;j<=m;++j)
{
char temp=getchar();
if(temp=='#')
{
for(int k=lastr+1;k<j;++k) rows[i][k]=j-lastr-1;
for(int k=lastc[j]+1;k<i;++k) columns[k][j]=i-lastc[j]-1;
lastr=j; lastc[j]=i;
}
}
for(int k=lastr+1;k<=m;++k) rows[i][k]=m-lastr;
}
for(int i=1;i<=m;++i)
for(int k=lastc[i]+1;k<=n;++k) columns[k][i]=n-lastc[i];
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) ans=max(ans,rows[i][j]+columns[i][j]);
cout<<ans-1<<endl;
return 0;
}
E
- 题意:给出一个二进制表示的L,满足题目的两个式子
- 题解:不难发现a,b两个数二进制表示时同一位不同时为1时满足条件,题目变为排列组合
- 举例:L=(1001011)2,方案数=
3^6+2*(3^3+2*(3^0+2))
;
#include <iostream>
#include <cstdio>
using namespace std;
const int mod=1e9+7;
string a;
int len;
long long ans,three=1;
int main()
{
cin>>a; len=a.length(); a=' '+a;
while(len--)
{
if(a[len+1]=='1') {ans=(three+2)%mod; break;}
three=(three*3)%mod;
}
three=(three*3)%mod;
while(len--)
{
if(a[len+1]=='1') ans=(ans*2+three)%mod;
three=(three*3)%mod;
}
cout<<ans<<endl;
return 0;
}