「NOIP模拟赛」刷漆
「问题描述」
Czy做完了所有的回答出了所有的询问,结果是,他因为脑力消耗过大而变得更虚了:)。帮助Czy恢复身材的艰巨任务落到了你的肩上。
正巧,你的花园里有一个由N块排成一条直线的木板组成的栅栏,木板从左到右依次标号1到N。这N块木板中,有M块木板前面放着一桶油漆。油漆有不同的颜色,每种颜色可以由一个大写字母表示(A到Z)。而你要求Czy用他的油漆刷子给栅栏刷上油漆。
已知Czy会选择一个前方放有油漆桶的木板开始他的任务。刷子蘸上油漆后,他开始随机地沿着栅栏走,他不会走出栅栏的范围。随机地走表示Czy会沿着他选择的方向一直走,然后随机在任何时候改变方向。沿着栅栏走只有两个方向,向前和向后。
你发现Czy刷油漆的过程总是符合下列规则:
- • 每个油漆桶里装着无限多的油漆;
- • 刷子上每次只有一种颜色的油漆,每次蘸油漆都会完全替换刷子上的油漆颜色;
- • 当Czy走到一个油漆桶前,他会首先用刷子蘸这个油漆桶里的油漆;
- • Czy每走过一个木板都会将这个木板刷成当前刷子上的油漆颜色。
已知木板可以被多次刷上油漆,每次都会完全覆盖之前的颜色。当所有木板都被刷上了油漆的时候,Czy才能停下来(当然他也可以继续刷到他想停下来为止)。你看着Czy在栅栏前来回舞动,突然想知道Czy停下来的时候栅栏有多少种可能的不同油漆方案。定义当至少有一块木板颜色不同时,两种油漆方案被视为是不同的。
请你输出不同的油漆方案数对109+9取模的值。
「输入」
输入文件为 paint.in。
输入的第一行包含两个整数N和M。
接下来M行,每行两个整数x和y,表示第y块木板前面有一个装着颜色为x的油漆的油漆桶。
「输出」
输出文件为 paint.out。
输出一行,包含一个整数,表示不同的油漆方案数对109 + 9取模的结果。
「输入输出样例」
paint.in |
paint.out |
6 2 A 2 B 6 |
4 |
「数据范围」
对于30% 的数据,1 ≤ M ≤ N ≤ 100。
对于100% 的数据, 1 ≤ M ≤ N ≤ 100000。
x是A到Z之间的大写字母;1 ≤ y ≤ N。
题解
首先头尾连续的无油漆桶段和两个相同颜色油漆桶间的段落不影响答案,去掉不考虑。然后对于任意两个连续的油漆桶中的段落(假设坐标分别为a,b)可以有b-a种油漆方案,则所有段落的方案数乘积即为所求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #define pa pair<int,int> #define inf (1LL<<60) #define mod 1000000009 #define ll long long using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ll ans=1; int n,m; struct data{int val,pos;}a[100005]; bool operator<(data a,data b) { return a.pos<b.pos; } int main() { n=read();m=read(); for(int i=1;i<=m;i++) { char ch[2]; scanf("%s",ch); a[i].val=ch[0]-'A'; a[i].pos=read(); } sort(a+1,a+m+1); for(int i=2;i<=m;i++) if(a[i].val!=a[i-1].val) ans=ans*(a[i].pos-a[i-1].pos)%mod; printf("%I64d",ans); return 0; } |