#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> using namespace __gnu_pbds; using namespace std; #define pb push_back #define st first #define nd second typedef long long ll; typedef long double ld; const ll I = 1000LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL; const ll M = 1000LL * 1000LL * 1000LL + 7LL; const int N = 40 * 1000 + 7; int tab1[N], tab2[N]; ll ans[N], il[N], last[N]; vector<int> inc[N]; void DoInc(int n) { for(int i = 2; i <= n; ++i) for(int j = i + 2; j <= n; j += i) inc[j].pb(i + 1); } inline ll F(ll a, ll b) { if(a > b) return 0LL; return (((a + b) * (b - a + 1)) / 2LL) % M; } inline int Il(int n, int k) { return max(0, (n - k + (k - 2)) / (k - 1)); } void Upd(ll tim, int j, int n2) { int p = il[j], k = il[j - 1] - 1; if(k != -1) p = max(p, 1); k = min(k, n2); //cout << tim << " " << "w: " << j << " " << p << " " << k << "\n"; ans[j] += (tim - last[j]) * F(n2 - k + 1, n2 - p + 1); ans[j] %= M; last[j] = tim; } void DoCnt(int n1, int n2) { for(int i = 1; i < n1; ++i) { int cur = 1; for(int j = 1; j <= n1 - i + 1; ++j) { last[j] = i; il[j] = 0; } for(int j = i + 1; j <= n1; ++j) { il[1] = j - i + 1; ++cur; if(cur > 2) { Upd(j - 1, 3, n2); ++il[2]; } Upd(j, 2, n2); for(int k = 0; k < (int)inc[cur].size(); ++k) { Upd(j - 1, inc[cur][k], n2); Upd(j - 1, inc[cur][k] + 1, n2); } for(int k = 0; k < (int)inc[cur].size(); ++k) ++il[inc[cur][k]]; if((tab1[j - 1] < tab1[j]) ^ (tab1[j] < tab1[j + 1])) cur = 1; } for(int j = 3; j <= n1 - i + 1; ++j) Upd(n1, j, n2); } } void Solve() { int n1, n2; cin >> n1 >> n2; DoInc(max(n1, n2)); for(int i = 1; i <= n1; ++i) cin >> tab1[i]; for(int i = 1; i <= n2; ++i) cin >> tab2[i]; DoCnt(n1, n2); for(int i = 1; i <= max(n1, n2); ++i) swap(tab1[i], tab2[i]); DoCnt(n2, n1); for(int i = 1; i <= max(n1, n2); ++i) swap(tab1[i], tab2[i]); for(int i = 1; i <= min(n1, n2); ++i) ans[2] += ((ll)(n1 - i + 1) * (ll)(n2 - i + 1)) % M; //Count(1, 7, 1); for(int i = 1; i <= n1 + n2; ++i) { ans[i] %= M; cout << ans[i] << " "; } cout << "\n"; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); //int t; cin >> t; //while(t--) Solve(); return 0; }
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | #include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update> using namespace __gnu_pbds; using namespace std; #define pb push_back #define st first #define nd second typedef long long ll; typedef long double ld; const ll I = 1000LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL; const ll M = 1000LL * 1000LL * 1000LL + 7LL; const int N = 40 * 1000 + 7; int tab1[N], tab2[N]; ll ans[N], il[N], last[N]; vector<int> inc[N]; void DoInc(int n) { for(int i = 2; i <= n; ++i) for(int j = i + 2; j <= n; j += i) inc[j].pb(i + 1); } inline ll F(ll a, ll b) { if(a > b) return 0LL; return (((a + b) * (b - a + 1)) / 2LL) % M; } inline int Il(int n, int k) { return max(0, (n - k + (k - 2)) / (k - 1)); } void Upd(ll tim, int j, int n2) { int p = il[j], k = il[j - 1] - 1; if(k != -1) p = max(p, 1); k = min(k, n2); //cout << tim << " " << "w: " << j << " " << p << " " << k << "\n"; ans[j] += (tim - last[j]) * F(n2 - k + 1, n2 - p + 1); ans[j] %= M; last[j] = tim; } void DoCnt(int n1, int n2) { for(int i = 1; i < n1; ++i) { int cur = 1; for(int j = 1; j <= n1 - i + 1; ++j) { last[j] = i; il[j] = 0; } for(int j = i + 1; j <= n1; ++j) { il[1] = j - i + 1; ++cur; if(cur > 2) { Upd(j - 1, 3, n2); ++il[2]; } Upd(j, 2, n2); for(int k = 0; k < (int)inc[cur].size(); ++k) { Upd(j - 1, inc[cur][k], n2); Upd(j - 1, inc[cur][k] + 1, n2); } for(int k = 0; k < (int)inc[cur].size(); ++k) ++il[inc[cur][k]]; if((tab1[j - 1] < tab1[j]) ^ (tab1[j] < tab1[j + 1])) cur = 1; } for(int j = 3; j <= n1 - i + 1; ++j) Upd(n1, j, n2); } } void Solve() { int n1, n2; cin >> n1 >> n2; DoInc(max(n1, n2)); for(int i = 1; i <= n1; ++i) cin >> tab1[i]; for(int i = 1; i <= n2; ++i) cin >> tab2[i]; DoCnt(n1, n2); for(int i = 1; i <= max(n1, n2); ++i) swap(tab1[i], tab2[i]); DoCnt(n2, n1); for(int i = 1; i <= max(n1, n2); ++i) swap(tab1[i], tab2[i]); for(int i = 1; i <= min(n1, n2); ++i) ans[2] += ((ll)(n1 - i + 1) * (ll)(n2 - i + 1)) % M; //Count(1, 7, 1); for(int i = 1; i <= n1 + n2; ++i) { ans[i] %= M; cout << ans[i] << " "; } cout << "\n"; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); //int t; cin >> t; //while(t--) Solve(); return 0; } |