Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- using namespace __gnu_pbds;
- using namespace std;
- //#define int long long
- #define mp make_pair
- #define pb push_back
- #pragma GCC optimize("Ofast")
- #pragma GCC optimize("unroll-loops")
- constexpr int INF = (int)1e9;
- constexpr int N = (int)5e5 + 111;
- constexpr int md = (int)1e9+7;
- constexpr int mdPower = (int)1e9+7 - 1;
- int mex(vector<int> v){
- if(v.empty())
- return 0;
- set<int> st(v.begin(),v.end());
- v = vector<int>(st.begin(),st.end());
- for(int i = 0; i < v.size(); i++)
- if(i != v[i])
- return i;
- return v.size();
- }
- int mex(set<int>& st){
- int c = 0;
- for(auto& x : st){
- if(x != c)
- return c;
- c++;
- }
- return st.size();
- }
- int CC[10];
- int mex(){
- int c = 0;
- for(int i = 0; i < 10; i++){
- if(CC[i] == 0)
- return i;
- }
- assert(false);
- return -1;
- }
- map<vector<int>,int> grundy;
- vector<int> PossibleMoves;
- int get(vector<int>& g){
- if(grundy.count(g))
- return grundy[g];
- vector<int> goGrundy;
- int sz = g.size();
- for(auto& x : PossibleMoves){
- if((int)g.size() - x <= 0 || g[sz-x-1] != 1)
- continue;
- vector<int> to = g;
- for(int j = 0; j < x; j++)
- to.pop_back();
- assert(to != g);
- goGrundy.pb(get(to));
- }
- // for(auto& x : goGrundy)
- // cerr << x << " ";
- // cerr << "\n";
- return grundy[g] = mex(goGrundy);
- }
- struct basis{
- vector<int> b;
- basis(){}
- void add(int x){
- for(auto& y : b)
- x = min(x,x^y);
- if(x != 0)
- b.pb(x);
- }
- bool check(int x){
- for(auto& y : b)
- x = min(x,y^x);
- return x == 0;
- }
- };
- int cnt[1<<6][101][10];
- int bpow(int a,int b){
- if(b == 0)
- return 1;
- if(b % 2 == 0){
- int t = bpow(a,b>>1);
- return 1ll*(t*t)%md;
- }
- return 1ll*a*bpow(a,b-1)%md;
- }
- int dp[2][9][9][9][9][9][9]; /// dp[pos][g1][g2][g3][g4][g5][g6]
- /// if g_i == INF then there is a zero at that position
- /// INF = 9
- void add(int& a,int b){
- a += b; if(a >= md) a-=md;
- }
- void add(long long& a,long long b){
- a += b; if(a >= md) a-=md;
- }
- int MEX = 0;
- void ADD(int x){
- CC[x]++;
- while(CC[MEX])
- MEX++;
- return;
- }
- void DEL(int x){
- CC[x]--;
- if(CC[x] == 0 && x < MEX)
- MEX = x;
- return;
- }
- typedef long long ll;
- vector<ll> operator *(vector<ll> a,vector<ll> b){
- vector<ll> c(8,0);
- for(int i = 0; i < 8; i++){
- for(int j = 0; j < 8; j++){
- add(c[i^j],1ll*a[i]*b[j]%md);
- }
- }
- return c;
- }
- vector<ll> NULL_MATRICE = {1,0,0,0,0,0,0,0};
- vector<ll> bpow(vector<ll>& a,ll b){
- if(b == 0)
- return NULL_MATRICE;
- if(b == 1)
- return a;
- if(b % 2 == 0){
- vector<ll> t = bpow(a,b>>1);
- return t*t;
- }
- return a * bpow(a,b-1);
- }
- void solve(){
- // for(int i = 0; i < 8; i++){
- // for(int j = 0; j < 8; j++){
- // cerr << i << " " << j << "\n";
- // for(int t = 0; t < 8; t++){
- // cerr << "(" << i << "," << t << ")*(" << t << "," << j << ")\n";
- // }
- // }
- // }
- //
- // return;
- int n;
- cin >> n;
- vector<pair<ll,int>> In;
- set<int> st;
- int C = 0;
- int mx = 0;
- for(int i = 0; i < n; i++){
- ll a,b;
- cin >> a >> b;
- In.pb(mp(a,b));
- st.insert(b);
- C += (b-1)*a;
- C %= mdPower;
- mx = max(mx,C);
- }
- int k;
- cin >> k;
- int PossibleMASK = 0;
- bool have[7] = {};
- for(int i = 0; i < k; i++){
- int a;
- cin >> a;
- PossibleMoves.pb(a);
- have[a] = 1;
- a--;
- PossibleMASK |= (1 << a);
- }
- for(int m1 = PossibleMASK; m1 < PossibleMASK+1; m1++){
- PossibleMoves.clear();
- for(int i = 0; i < 6; i++){
- if(m1 >> i & 1){
- PossibleMoves.pb(i+1);
- }
- }
- memset(dp,0,sizeof dp);
- dp[0][8][8][8][8][8][8] = 1;
- #pragma GCC ivdep
- for(int i = 1; i <= 100; i++){
- int g[6];
- #pragma GCC ivdep
- for(g[0] = 0; g[0] < 9; g[0]++){
- if(have[6])
- ADD(g[0]);
- #pragma GCC ivdep
- for(g[1] = 0; g[1] < 9; g[1]++){
- if(have[5])
- ADD(g[1]);
- #pragma GCC ivdep
- for(g[2] = 0; g[2] < 9; g[2]++){
- if(have[4])
- ADD(g[2]);
- #pragma GCC ivdep
- for(g[3] = 0; g[3] < 9; g[3]++){
- if(have[3])
- ADD(g[3]);
- #pragma GCC ivdep
- for(g[4] = 0; g[4] < 9; g[4]++){
- if(have[2])
- ADD(g[4]);
- #pragma GCC ivdep
- for(g[5] = 0; g[5] < 9; g[5]++){
- /// HERE SHOULD BE NOT THIS
- /// ADD ONLY POS WE CAN COME FROM
- // gg.clear();
- // for(auto& x : PossibleMoves) gg.push_back(g[6-x]);
- if(have[1])
- ADD(g[5]);
- int m = MEX;
- add(cnt[m1][i][m],dp[0][g[0]][g[1]][g[2]][g[3]][g[4]][g[5]]);
- add(dp[1][g[1]][g[2]][g[3]][g[4]][g[5]][m],
- dp[0][g[0]][g[1]][g[2]][g[3]][g[4]][g[5]]);
- add(dp[1][g[1]][g[2]][g[3]][g[4]][g[5]][8],
- dp[0][g[0]][g[1]][g[2]][g[3]][g[4]][g[5]]);
- if(have[1])
- DEL(g[5]);
- }
- if(have[2])
- DEL(g[4]);
- }
- if(have[3])
- DEL(g[3]);
- }
- if(have[4])
- DEL(g[2]);
- }
- if(have[5])
- DEL(g[1]);
- }
- if(have[6])
- DEL(g[0]);
- }
- for(g[0] = 0; g[0] < 9; g[0]++){
- for(g[1] = 0; g[1] < 9; g[1]++){
- for(g[2] = 0; g[2] < 9; g[2]++){
- for(g[3] = 0; g[3] < 9; g[3]++){
- for(g[4] = 0; g[4] < 9; g[4]++){
- for(g[5] = 0; g[5] < 9; g[5]++){
- dp[0][g[0]][g[1]][g[2]][g[3]][g[4]][g[5]] = dp[1][g[0]][g[1]][g[2]][g[3]][g[4]][g[5]];
- dp[1][g[0]][g[1]][g[2]][g[3]][g[4]][g[5]] = 0;
- }
- }
- }
- }
- }
- }
- // cerr << i << "\n";
- // cout << "cnt[" << m1 << "][" << i << "] = {";
- // for(int j = 0; j < 8; j++){
- // cout << cnt[m1][i][j];
- // if(j != 7)
- // cout << ",";
- // }
- // cout << "};\n";
- }
- }
- // return;
- vector<ll> A(8,0);
- A[0] = 1;
- for(auto&[x,y] : In){
- vector<ll> B(8,0);
- for(int i = 0; i < 8; i++){
- B[i] = cnt[PossibleMASK][y][i];
- }
- // cerr << "B:\n";
- // for(auto& X : B){
- // cerr << X << " ";
- // }
- // cerr << "\n";
- // cerr << "A:\n";
- // for(auto& X : A){
- // cerr << X << " ";
- // }
- // cerr << "\n";
- A = A * bpow(B,x);
- }
- cout << (1ll * A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7]) % md << "\n";
- return;
- }
- signed main(){
- ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
- // freopen("input.txt","r",stdin);
- // freopen("output.txt","w",stdout);
- int tests = 1;
- // cin >> tests;
- for(int test = 1; test <= tests; test++){
- solve();
- }
- return 0;
- }
- /**
- Possible: 1 2 3
- 1 0 0 0 0 0 0 0
- 1 1 0 0 0 0 0 0
- 1 2 1 0 0 0 0 0
- 1 3 3 1 0 0 0 0
- 9 3 3 1 0 0 0 0
- 17 8 5 2 0 0 0 0
- 25 24 11 4 0 0 0 0
- cnt[n][g][mask] - количество последовательностей длины n, которые имеют число гранди g и последние k чисел в ней - mask
- cnt[n][mex][mask]
- 6^6
- dp[n][mex][mask]
- for(int i = 0; i < n; i++){
- for(int mask = 0; mask < (1 << 6); mask++){
- }
- }
- b -> a -> cur
- b -> cur
- cnt[pos][g1][g2][g3][g4][g5][g6]
- for(int i = 0; i < n; i++){
- for(int j = 0; j < n; j++){
- for(int t = 0; t < n; t++){
- add(g[i][j],a[i][t]*b[t][j])
- cnt[1]
- cnt[2]
- cnt[3]
- cnt[4]
- cnt[5]
- cnt[6]
- 0 0
- A(0,0)*B(0,0)
- A(0,1)*B(1,0)
- A(0,2)*B(2,0)
- A(0,3)*B(3,0)
- A(0,4)*B(4,0)
- A(0,5)*B(5,0)
- A(0,6)*B(6,0)
- A(0,7)*B(7,0)
- 0 1
- A(0,0)*B(0,1)
- A(0,1)*B(1,1)
- A(0,2)*B(2,1)
- A(0,3)*B(3,1)
- A(0,4)*B(4,1)
- A(0,5)*B(5,1)
- A(0,6)*B(6,1)
- A(0,7)*B(7,1)
- **/
Advertisement
Add Comment
Please, Sign In to add comment