冲刺Noip2017模拟赛8 解题报告——五十岚芒果酱
1、鼎纹
【问题描述】 据说鼎纹的 种制造 式是 铜模印出来的,这是我国古代劳动 智慧 的结晶。铜模印过的地 ,会留下深深的印记,经过时间的炼化,洗 练成历史的遗存。 聪明的古代劳动人民拥有一个 a 行 b 列的铜模,每个位置要么是 0(代表 这个点是平的),要么是 1(代表这个点是凸起的)。他们想造 个 n 行 m 列 的鼎 ,其中每个位置也都是 0 或 1,表示经过若干 次印后,每个位置的结果。 有一些要求。铜模是不能旋转和翻转的;在印的过程当中,铜模的凸起不 能出现在鼎面的外面(平的部分是可以出现在外面的),鼎面上的同一个位置 不能被多个凸起印下(在任意两次印时,鼎面上不存在一个点,使得这两次都 有铜模上为 1 的点覆盖它)。 请你判断这个鼎面能不能被印出来。 【输入格式】 输入文件件名为 grain.in。 本题多测。 第一行,一个整数 T ,表示测试 点数量。接下来 T 个测试点,每 个测试点中: 第一行包含 4 个整数 n,m,a,b。 接下来 n 行 ,每行 m 个字符,描述鼎面 。“0”表示 平,“1”表示凸起。接下来 a 行,每行 b 个字符, 描述铜模。“0”表示平,“1”表示凸起。 【输出格式】 输出 件名为 grain.out。 共有 T 行 ,对于每个测试点,输出 “YES”(能)或“NO”(不能)。 【样例】 grain.in 2 3 4 4 2 1100 0110 1100 10 01 10 00 2 2 2 2 11 11 01 10 grain.out YES NO 【数据规模与约定】 对于 70% 的数据,n,m,a, b <= 50。 对于 100% 的数据,1 <= T <=10; 1<=n,m, a, b <= 1000。 【问题描述】 据说鼎纹的 种制造 式是 铜模印出来的,这是我国古代劳动 智慧 的结晶。铜模印过的地 ,会留下深深的印记,经过时间的炼化,洗 练成历史的遗存。 聪明的古代劳动人民拥有一个 a 行 b 列的铜模,每个位置要么是 0(代表 这个点是平的),要么是 1(代表这个点是凸起的)。他们想造 个 n 行 m 列 的鼎 ,其中每个位置也都是 0 或 1,表示经过若干 次印后,每个位置的结果。 有一些要求。铜模是不能旋转和翻转的;在印的过程当中,铜模的凸起不 能出现在鼎面的外面(平的部分是可以出现在外面的),鼎面上的同一个位置 不能被多个凸起印下(在任意两次印时,鼎面上不存在一个点,使得这两次都 有铜模上为 1 的点覆盖它)。 请你判断这个鼎面能不能被印出来。 【输入格式】 输入文件件名为 grain.in。 本题多测。 第一行,一个整数 T ,表示测试 点数量。接下来 T 个测试点,每 个测试点中: 第一行包含 4 个整数 n,m,a,b。 接下来 n 行 ,每行 m 个字符,描述鼎面 。“0”表示 平,“1”表示凸起。接下来 a 行,每行 b 个字符, 描述铜模。“0”表示平,“1”表示凸起。 【输出格式】 输出 件名为 grain.out。 共有 T 行 ,对于每个测试点,输出 “YES”(能)或“NO”(不能)。 【样例】 grain.in 2 3 4 4 2 1100 0110 1100 10 01 10 00 2 2 2 2 11 11 01 10 grain.out YES NO 【数据规模与约定】 对于 70% 的数据,n,m,a, b <= 50。 对于 100% 的数据,1 <= T <=10; 1<=n,m, a, b <= 1000。
tag:模拟
思路:题意一定要看懂哦。用铜模的1去消除鼎的1,铜模的每个1都必须找到对应的,最后要保证鼎的1被消完。暴力模拟能拿60分。通过观察我们发现,这个题目跟0没有什么关系,所以只要记录1的位置。那么消除呢,必须是两个矩阵偏左上角的1为起始点,如果不这样,就会有左上方多余的1没被消除。每次默认这两个1必须对上,然后用之前记录的铜模其他的1与起始1的相对位置去找。记得每行读入整个字符串不然scanf("%c")会T。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #define maxn 1010 7 using namespace std; 8 int T,n,m,a,b,cnt1,cnt2,mp[maxn][maxn],x[maxn*maxn],y[maxn*maxn],X[maxn*maxn],Y[maxn*maxn]; 9 char ch[maxn]; 10 void init() 11 { 12 for(int i=1;i<=n;++i) 13 for(int j=1;j<=m;++j) 14 mp[i][j]=0; 15 for(int i=1;i<=cnt1;++i) x[i]=y[i]=0; 16 for(int i=1;i<=cnt2;++i) X[i]=Y[i]=0; 17 cnt1=cnt2=0; 18 } 19 bool check(int xx,int yy) 20 { 21 mp[xx][yy]=0; 22 for(int i=2;i<=cnt2;++i){ 23 int XX=xx+X[i],YY=yy+Y[i]; 24 if(XX<1||XX>n||YY<1||YY>m||!mp[XX][YY]) return false; 25 mp[XX][YY]=0; 26 } 27 return true; 28 } 29 void solve() 30 { 31 init(); 32 scanf("%d%d%d%d",&n,&m,&a,&b); 33 for(int i=1;i<=n;++i){ 34 scanf("%s",ch+1); 35 for(int j=1;j<=m;++j){ 36 if(ch[j]-'0'){ 37 x[++cnt1]=i; 38 y[cnt1]=j; 39 mp[i][j]=1; 40 } 41 } 42 } 43 //记录鼎的1 44 for(int i=1;i<=a;++i){ 45 scanf("%s",ch+1); 46 for(int j=1;j<=b;++j){ 47 if(ch[j]-'0'){ 48 X[++cnt2]=i; 49 Y[cnt2]=j; 50 } 51 }//记录模的1 52 } 53 for(int i=2;i<=cnt2;++i){ 54 X[i]-=X[1]; 55 Y[i]-=Y[1]; 56 }//模版的几个1到第一个1的距离 57 for(int i=1;i<=cnt1;++i) 58 if(mp[x[i]][y[i]]) 59 if(!check(x[i],y[i])){ 60 puts("NO"); 61 return; 62 } 63 puts("YES"); 64 } 65 int main() 66 { 67 //freopen("grain.in","r",stdin); 68 //freopen("grain.out","w",stdout); 69 scanf("%d",&T); 70 while(T--) solve(); 71 return 0; 72 }
2、看球赛
2200 年 里奥迪奥带领的十星巴西对战莱昂纳多带领的阿根廷的世界杯决赛马 上开始了!前来在巨型球场观看比赛的观众数不甚数,但是由于突如其来的系统 原因,大家不能网上购票,只能到售票窗口,排成长龙买票. 按售票处规定,每一个限购一张门票,且每一张门票 50 美元。 在排成长龙的球 迷中有 n 个人手持 50 美元,另外有 n 个人手持 100 美元。假设售票处开始的时 候没有零钱,试问这 2n 个球迷有多少种排队方式使得售票处不会出现找不出钱 的尴尬局面,导致拖延球迷看球时间。 【输入与输出说明】 输入两行,第一行一个正整数 T,表示数据个数。 第二行有 T 个正整数,n1,n2,....nT. 输出 T 行,每一行为被 10^9+7 模过的结果。 【样例输入1】 1 2 【样例输出1】 2 【样例输入2】 2 2 5 【样例输出2】 2 42 【样例说明】 例如当 n=2 时,用 A 表示手持面值 50 美元的球迷,用 B 表示手持面值为 100 美 元的球迷,则最多可得到以下两组不同的排队方式使得售票处不会出现找不出钱 的情况。 售票处 A A B B 售票处 A B A B 【数据范围】 对于 10% n <= 10, T <= 10 对于 20% n <= 15, T <= 10 对于 60% n <= 2000, T <= 10 对于其中 20% 2000 < n <= 10^7, T <= 3 对于其中 20% 10^7 < n <= 3*10^7, T = 1
tag:数学
思路:裸的卡特兰数(可是我不会写啊,只能打表)。公式是C(2n,n)/(n+1)。注意要用逆元哦。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int mod=1e9+7; 8 int T,n; 9 int ksm(int x,int y) 10 { 11 int ret=1,b=y; 12 while(b) 13 { 14 if(b&1) ret=1ll*ret*x%mod; 15 x=1ll*x*x%mod; 16 b>>=1; 17 } 18 return ret; 19 } 20 int solve() 21 { 22 int ret1=1,ret2=1; 23 for(int i=2;i<=n;++i){ 24 ret1=1ll*ret1*(n+i)%mod; 25 ret2=1ll*ret2*i%mod; 26 } 27 return 1ll*ret1*ksm(ret2,mod-2)%mod; 28 } 29 int main() 30 { 31 //freopen("football.in","r",stdin); 32 //freopen("football.out","w",stdout); 33 scanf("%d",&T); 34 while(T--){ 35 scanf("%d",&n); 36 printf("%d\n",solve()); 37 } 38 return 0; 39 }
再补充:n个1 m个0 公式为C(n+m,m)-C(n+m,m-1)
3、靶形数独
单独拿出来写题解了,-->链接<--
芒果君:分割线懒得画=_= 最近好颓,真的很想改变现状,我不想做一个只会打表的OIer 要好好学习QAQ