DAY1 - 8.3
T1 apple
【问题描述】
陶陶家门前有一块 n 行 m 列的耕地
有些格子可以种苹果(用 1 表示),一些无法种苹果(用 0 表示),并且相邻格子无法都种苹果
陶陶想知道有多少种种植方案(一颗也不种也是可以的)
【输入文件】
输入文件为 apple.in
第一行包含用空格隔开的两个整数 n,m
接下来 n 行每行 m 个数,为1或0,表示能否种植
【输出文件】
输出文件为 apple.out
共一行,一个整数ans,表示方案数。
【输入样例1】
1 5
1 1 1 1 1
【输出样例1】
13
【输入样例2】
1 10
1 1 1 1 0 1 1 0 1 1
【输出样例2】
72
【输入样例3】
2 10
1 1 0 1 1 1 0 1 1 1
1 0 1 1 1 1 0 0 1 0
【输出样例3】
1305
【数据规模和约定】
对于前 30%的数据,满足 n=1,所有格子都能种苹果。
对于另外 20%的数据,满足 n=1。
对于另外 20%的数据,保证每行只有一个位置能种苹果。
对于 100%的数据,满足 n<=2,m<=10
60分代码
1 #include<cstdio>
2 using namespace std;
3 const int MAXN=2,MAXM=10;
4 int n,m,a[MAXN][MAXM],ans;
5 bool b[MAXN+2][MAXM+2];
6 int ct[11]={1,2,3,5,8,13,21,34,55,89,144};
7 int main()
8 {
9 freopen("apple.in","r",stdin);
10 freopen("apple.out","w",stdout);
11 scanf("%d%d",&n,&m);
12 for(int i=1;i<=n;i++)
13 for(int j=1;j<=m;j++)
14 scanf("%d",&a[i][j]);
15 if(n==1)//n=1
16 {
17 for(int i=1;i<=m;i++)
18 ans=1;
19 for(int i=1,j=0;i<=m+1;i++)
20 {
21 if(a[1][i]==0)
22 {
23 ans*=ct[j];
24 j=0;
25 }
26 else
27 {
28 j++;
29 }
30 }
31 printf("%d",ans);
32 return 0;
33 }
34 else//n==2
35 {
36 int pos;
37 for(int i=1;i<=m;i++)
38 if(a[1][i]==1)
39 pos=i;
40 if(a[2][pos]==1)
41 {
42 printf("3");
43 return 0;
44 }
45 else
46 {
47 printf("4");
48 return 0;
49 }
50
51 }
52 return 0;
53 }
//不知道为什么9个1过不了,不然就70分
思路:
当n=1,全部为1时,找规律可得为斐波那契数列,故记录ct[]为斐波那契数直接调用
当n=1,不全为1时,以0拆分为若干段,每段的情况相乘即为答案
当每行只有一个位置有苹果时,判断是否在同一列,在同一列答案为3,否则答案为4
理论上能骗到70分
AC代码
1 //二进制模拟
2 #include<string.h>
3 #include<iostream>
4 using namespace std;
5 #define rep(i,h,t) for (int i=h;i<=t;i++)
6 #define me(x) memset(x,0,sizeof(x))
7 int a[30][30],p[30][30],n,m;
8 int main()
9 {
10 freopen("apple.in","r",stdin);
11 freopen("apple.out","w",stdout);
12 ios::sync_with_stdio(false);//加速cin,cout
13 cin>>n>>m;
14 int num=0;
15 rep(i,1,n)
16 rep(j,1,m)
17 {
18 cin>>a[i][j];
19 if (a[i][j]) num++;//统计可种植点数
20 }
21 int ans=0;
22 rep(i,0,(1<<num)-1)//从num个0模拟到num个1
23 {
24 me(p);//重置种植情况
25 rep(j,1,num)//num个点的种植情况存入p数组
26 {
27 int k=(i>>(j-1))&1;//取第j位
28 int cnt=0,i1,j1;
29 for (i1=1;i1<=n;i1++)
30 {
31 for (j1=1;j1<=m;j1++)
32 {
33 if (a[i1][j1]) cnt++;
34 if (cnt==j) break;//找到第cnt个点的坐标i1,j1时跳出
35 }
36 if (cnt==j) break;
37 }
38 p[i1][j1]=k;//种植情况存入
39 }
40 bool tt=1;//初始设为合法
41 rep(i,1,n)
42 rep(j,1,m)
43 {
44 if (j>1&&p[i][j]&&p[i][j-1]) tt=0;//横向判断非法
45 if (i>1&&p[i][j]&&p[i-1][j]) tt=0;//纵向判断非法
46 if (!tt) break;//非法即跳出
47 }
48 if (tt) ans++;//合法则记录
49 }
50 cout<<ans<<endl;
51 return 0;
52 }
53 //时间复杂度:O(2^(n*m))<=2^20≈2e7
T2 music
【问题描述】
一共唱 n 个音符,每个音符持续 b[i]个时间。 比如第一个音符,在 0~b[1]-1 时间内歌唱。 比如第二个音符,在 b[1]~b[1]+b[2]-1 时间内歌唱。 以此类推。。。
现在有 q 组询问,每组询问有一个时刻 t。
求对于每一个询问 t,赤羽所唱的音符。
【输入文件】
输入文件为 music.in。
第一行两个整数 n,q。
第2~n+1行 n 个数表示每个音符持续的时间。
【输出文件】
输出文件为 music.out。 共n行。 每行输出对应的音符
【输入样例1】
3 5
2
1
3
2
3
4
0
1
【输出样例1】
2
3
3
1
1
【数据规模和约定】
对于 30%的数据 n<=1000,b[i]<=1000,q=1
另外 30%的数据 n<=1000,b[i]<=10000,q<=10000
对于 100%的数据 n<=10000,b[i]<=10000,q<=1e5
AC代码
#include<cstdio>
#include<algorithm>
const int MAXN=10000,MAXQ=1e5;
int n,q,b[MAXN+2],a[MAXN+2];
using namespace std;
int main()
{
freopen("music.in","r",stdin);
freopen("music.out","w",stdout);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
a[i]=a[i-1]+b[i];//唱完第i个音符结束的时间
if(i==1)
a[i]--;
}
for(int i=1;i<=q;i++)
{
int ask;
scanf("%d",&ask);
int pos=lower_bound(a+1,a+n+1,ask)-a;
printf("%d\n",pos);
}
}
//STL直接带舒服