Codeforces Round #596 (Div. 2, based on Technocup 2020 Elimination Round 2)
B2 - TV Subscriptions (Hard Version)
遍历,维护一个set和set<pair<int,int>>即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6+7; 5 const ll mod = 1e9 + 9; 6 #define afdafafafdafaf y1; 7 int ar[maxn], n, m, k; 8 9 int d[maxn]; 10 int main() 11 { 12 int t; 13 scanf("%d", &t); 14 while(t--){ 15 scanf("%d%d%d", &n, &m, &k); 16 for(int i=1;i<=n;i++)scanf("%d", ar+i); 17 for(int i=1;i<=n;i++)d[ar[i]] = 0; 18 set<int> s; 19 set<pair<int,int> > sp; 20 for(int i=1;i<=k;i++){ 21 d[ar[i]]++; 22 } 23 for(int i=1;i<=k;i++){ 24 s.insert(ar[i]); 25 sp.insert(make_pair(ar[i], d[ar[i]])); 26 } 27 int ans = s.size(); 28 for(int i = k + 1; i <= n; i++){ 29 int x = ar[i - k]; 30 sp.erase(make_pair(x, d[x])); 31 d[x]--; 32 if(d[x] > 0){ 33 sp.insert(make_pair(x, d[x])); 34 } 35 else{ 36 s.erase(x); 37 } 38 x = ar[i]; 39 sp.erase(make_pair(x, d[x])); 40 d[x]++; 41 sp.insert(make_pair(x, d[x])); 42 if(d[x] == 1)s.insert(x); 43 ans = min(ans, int(s.size())); 44 } 45 printf("%d\n", ans); 46 } 47 48 return 0; 49 }
暴力尝试。。。。
try a try, ac is ok
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6+7; 5 const ll mod = 1e9 + 9; 6 #define afdafafafdafaf y1; 7 int ar[maxn], n, m, k; 8 9 int d[maxn]; 10 int main() 11 { 12 ll n, p; 13 int flag = 0; 14 scanf("%lld%lld", &n, &p); 15 for(ll i=1;i<=int(3e5);i++){ 16 ll x = n - p * i, pre = x; 17 int ins = 0; 18 while(x > 0){ 19 if(x & 1)ins++; 20 x /= 2; 21 } 22 if(i <= pre && i >= ins){ 23 printf("%d\n", i); 24 flag = 1; 25 break; 26 } 27 } 28 if(flag != 1){ 29 printf("-1\n"); 30 } 31 return 0; 32 }
一个数如果可以形成x^k的形式,那他的每一个质因子的次幂一定是k的倍数,对每一个数的每个质因子幂%k,对k取补值(即补值*原值就是x^k的形式)
找出能和每个数相乘能符合条件的最小补值,求个对数集即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6+7; 5 const ll mod = 1e9 + 9; 6 #define afdafafafdafaf y1; 7 int ar[maxn], n, m, k; 8 9 int d[maxn], rev[maxn]; 10 int main() 11 { 12 scanf("%d%d", &n, &k); 13 for(int i=1;i<=n;i++)scanf("%d", ar+i); 14 for(int in=1;in<=n;in++){ 15 ll x = ar[in]; 16 ll re = 1; 17 for(int i=2; i<=sqrt(x);i++){ 18 int ins = 0; 19 ll base = 1, ss = 1; 20 while(x % i == 0){ 21 ss *= i; 22 ins++; 23 x /= i; 24 } 25 if(ins > 0){ 26 for(int j=0;j<k;j++){ 27 base *= i; 28 if(base > ll(1e10)){ 29 base = 0; 30 ar[in] = 0; 31 re = 0; 32 break; 33 } 34 } 35 if(base == 0)break; 36 while(ss % base == 0){ 37 ss /= base; 38 ar[in] /= base; 39 } 40 assert(base % ss == 0); 41 if(ss != 1)re *= (base / ss); 42 if(re > int(1e5)){ 43 re = 0; 44 ar[in] = 0; 45 break; 46 } 47 } 48 } 49 if(x > 1 && re != 0){ 50 for(int j = 0; j < k - 1; j++){ 51 re *= x; 52 if(re > int(1e5)){ 53 re = 0; 54 ar[in] = 0; 55 break; 56 } 57 } 58 } 59 if(ar[in] > 0)d[ar[in]]++; 60 rev[in] = re; 61 //cout<< ar[in] << ' ' << rev[in] << '\n'; 62 } 63 ll sum = 0; 64 for(int i=1;i<=n;i++){ 65 if(rev[i] > int(1e5) || rev[i] == 0)continue; 66 sum += d[rev[i]]; 67 if(ar[i] == rev[i] && ar[i] > 0)sum--; 68 } 69 printf("%lld\n", sum / 2); 70 71 72 return 0; 73 }
对每个点求向右,向下能走到的最远的点
每次dp的时候,只需要计算左边的点向下走的次数,上面的点向右的次数即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2e3+7; 5 const ll mod = 1e9 + 7; 6 #define afdafafafdafaf y1; 7 int ar[maxn], n, m, k; 8 9 char g[maxn][maxn]; 10 ll s[2][maxn][maxn<<2]; 11 void add(int ins, int x, int y, ll val){ 12 while(y <= max(n, m)){ 13 s[ins][x][y] += val + mod; 14 s[ins][x][y] %= mod; 15 y += y & (-y); 16 } 17 } 18 ll que(int ins, int x, int y){ 19 ll ans = 0; 20 while(y > 0){ 21 ans += s[ins][x][y] + mod; 22 ans %= mod; 23 y -= y & (-y); 24 } 25 return ans; 26 } 27 void add_all(int ins, int x, int l, int r, ll val){ 28 add(ins, x, l, val); 29 add(ins, x, r+1, -val); 30 } 31 int r[maxn][maxn], c[maxn][maxn], f_r[maxn], f_c[maxn]; 32 ll ans[maxn][maxn]; 33 int main() 34 { 35 scanf("%d%d", &n, &m); 36 for(int i=1;i<=n;i++){ 37 scanf("%s", g[i] + 1); 38 } 39 for(int i=1;i<=n;i++){ 40 //cout << g[i] + 1 << '\n'; 41 } 42 for(int i = n; i >= 1; i--){ 43 for(int j = m; j >= 1; j--){ 44 r[i][j] = r[i][j+1] + (g[i][j] == '.'); 45 c[i][j] = c[i+1][j] + (g[i][j] == '.'); 46 } 47 } 48 /* 49 for(int i=1;i<=n;i++){ 50 for(int j=1;j<=m;j++)cout<< r[i][j] << ' '; cout << '\n'; 51 } 52 for(int i=1;i<=n;i++){ 53 for(int j=1;j<=m;j++)cout<< c[i][j] << ' '; cout << '\n'; 54 } 55 cout<<"\n\n"; 56 */ 57 for(int i=1;i<=n;i++){ 58 for(int j=1;j<=m;j++){ 59 ll rs = 0, cs = 0; 60 if(i == 1 && j == 1){ 61 rs = cs = 1; 62 } 63 if(j != 1){ 64 rs = que(0, i, j); 65 } 66 int len1; 67 len1 = c[i+1][j]; 68 add_all(1, j, i+1, i+len1, rs); 69 if(i != 1){ 70 cs = que(1, j, i); 71 } 72 int len2 = r[i][j+1]; 73 add_all(0, i, j+1, j+len2, cs); 74 if(i == 1 && j == 1)ans[i][j] = 1; 75 else ans[i][j] = rs + cs; 76 //cout<< i <<' ' << j << ' ' << rs << ' ' << cs << ' ' << len1 << ' ' << len2 << '\n'; 77 } 78 } 79 printf("%lld\n", ans[n][m] % mod); 80 return 0; 81 }
拖神的dp复杂度更牛逼
附个链接吧
https://codeforc.es/contest/1246/submission/63454015