In Gensokyo, Keine is a teacher in Human Village. Since there are many naughty students in her class, Keine keeps a log of all in/out behaviors of all students, in chronological order.
Following is a part of an example log:
Rumia in
Cirno out
Rumia out
One day, Keine found that the log had been damaged. All the names of students were lost. Keine could remember that some of the records were relevant. Record u and record v are considered relevant if and only if:
-
Record u and v are of the same student;
-
Record u is 'I' and record v is 'O';
-
Record u is before record v;
-
No other record between record u and record v is of this student.
For example, the first record and the third record in the example log are relevant, since it was a log of Cirno entering and then exiting. However, there are still many possibilities for the whole log. Keine wants to know how many possible versions are there for the damaged log.
Notice that the classroom was empty at both the beginning and the ending of the log.
For each test case:
The first line contains three integers: n, m, k. n (1 ≤ n ≤ 100 000) is the length of the log. m (1 ≤ m ≤ n/2) is the number of relevant pairs that Keine could remember. k (1 ≤ k ≤ 50) is the number of students who may appear in the log.
The second line contains a string, which only consists of 'I' and 'O', indicates the in/out behaviors in the log.
For next m lines, each line contains two integers u and v (u < v), indicate that the u-th and the v-th records are relevant. The u-th record must be 'I' and the v-th record must be 'O'.
3 8 2 3 IIOIOIOO 1 3 4 5 8 2 3 IIOOIOIO 2 3 5 6 6 2 3 IOIOIO 1 2 3 4
48 54 27
其中in表示在教室外面可以进教室的人数;
out表示在教室里面可以出来的人数;
经过这样的表示,就可以逐渐使用乘法原理实现了;
需要注意的是并不是每次进去教室out都要++,如果是在题目的m给出的要求中,那么out就不需要++,可以自行理解一下,很容易想明白。
具体上代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const long long mode = 1000000000+7;
int main()
{
char s[100100];
bool vis[100100];
long long n,m,k;
long long T;
cin >> T;
while(T--)
{
cin >> n >> m >> k;
scanf(" %s",s);
memset(vis, false, sizeof(vis));
int a,b;
for(int i=1; i<=m; i++)
{
cin >> a >> b;
vis[a-1] = vis[b-1] = 1;
}
// 注意要用long long 类型
long long in = k; //理解为刚开始有k人可以进教室
long long out = 0; // 刚开始教室是空的,所以out=0;
long long sum = 1; // 用来记数
for(int i=0; i<n; i++)
{
if(s[i]=='I')
{
sum = sum*in%mode; // 如果使进教室的话,那么有in个人可以进来 ,也就是有in种情况
if(vis[i]==0) out++; // 如果没有指明要从哪个位置出来(也就是从那个‘O’出来都可以),那么out++;
in--; // 有人进教室了,所以外面的人数in--;
}
else
{
if(vis[i]==0) // 原理同上,可以自行理解一下
{
sum = sum*out%mode;
out--;
}
in++;
}
}
cout << sum%mode << endl;
}
return 0;
}
俺真菜.