牛客练习赛60
(先划划水)
[Toc]
A 题
签到题
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #define iinf 0x3f3f3f3f #define linf (1ll<<60) #define eps 1e-8 #define maxn 1000010 #define maxe 1000010 #define cl(x) memset(x,0,sizeof(x)) #define rep(i,a,b) for(i=a;i<=b;i++) #define drep(i,a,b) for(i=a;i>=b;i--) #define em(x) emplace(x) #define emb(x) emplace_back(x) #define emf(x) emplace_front(x) #define fi first #define se second #define pb push_back #define de(x) cerr<<#x<<" = "<<x<<endl #define __i __int128 using namespace std; using namespace __gnu_pbds; typedef long long ll; typedef pair<int,int> pii; typedef pair<ll,ll> pll; ll read(ll x=0) { ll c, f(1); for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f; for(;isdigit(c);c=getchar())x=x*10+c-0x30; return f*x; } int n , k, m ; vector<int> add(vector<int> &A, vector<int> &B) { if (A.size() < B.size()) return add(B, A); vector<int> C; int t = 0; for (int i = 0; i < A.size(); i ++ ) { t += A[i]; if (i < B.size()) t += B[i]; C.push_back(t % 10); t /= 10; } if (t) C.push_back(t); return C; } ll ar[200010]; int f[200010]; int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin >> n; map<ll , ll > mp; for(int i=0;i<n;i++) { cin >>ar[i];bitset<31 > be(ar[i]); for(int i=0;i<=31;i++) if(be[i]==1)mp[i]++; } ll sum =0 ; for(int i=0 ;i<n;i++){ bitset<31>be(ar[i]); for(int j=0;j<=31;j++){ if(be[j])sum +=(1<<j)*mp[j]; } //cout<<num<<endl; } cout<<sum<<endl; return 0; }
B 题
签到题
#include <bits/stdc++.h> using namespace std; #define ll long long const int maxn = 1005; ll a[maxn],b[maxn]; ll dis[maxn][maxn]; const ll mod = 998244353; int main() { ll n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]>>b[i]; ll ans = 0; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++) { dis[i][j] = abs(a[i] - a[j]) + abs(b[i] - b[j]); ans += 1ll*(dis[i][j]*(n - 2)); ans %= mod; } } cout<<ans<<endl; return 0; }
C 题
题外话
以后记住了这样的递推是DP 了。。
思路
设f[i][j],是前i个字符里面长度为j个的
- 然后先不考虑重复的那么f[i][j] = f[i-1][j] + f[i-1]j-1
- 考虑重复的,设置一个判断这个字符是否出现的数组,然后,会发现其实我们只需要减去这个字符上一个位置的f,就行了,(其实就是把上一个相同字符的次数减去,然后换上当前字符的)
代码
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #define iinf 0x3f3f3f3f #define linf (1ll<<60) #define eps 1e-8 #define maxn 1000010 #define maxe 1000010 #define cl(x) memset(x,0,sizeof(x)) #define rep(i,a,b) for(i=a;i<=b;i++) #define drep(i,a,b) for(i=a;i>=b;i--) #define em(x) emplace(x) #define emb(x) emplace_back(x) #define emf(x) emplace_front(x) #define fi first #define se second #define pb push_back #define de(x) cerr<<#x<<" = "<<x<<endl #define __i __int128 using namespace std; using namespace __gnu_pbds; typedef long long ll; typedef pair<int,int> pii; typedef pair<ll,ll> pll; ll read(ll x=0) { ll c, f(1); for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f; for(;isdigit(c);c=getchar())x=x*10+c-0x30; return f*x; } int n , k, m ; vector<int> add(vector<int> &A, vector<int> &B) { if (A.size() < B.size()) return add(B, A); vector<int> C; int t = 0; for (int i = 0; i < A.size(); i ++ ) { t += A[i]; if (i < B.size()) t += B[i]; C.push_back(t % 10); t /= 10; } if (t) C.push_back(t); return C; } ll f[1010][1010]; ll pre[100010]; ll mod = 1e9+7;char s[10010]; int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin >>n>> m ; cin >>s+1; f[0][0] =1 ; for(int i=1 ;i<=n;i++){ f[i][0]=1 ; for(int j=1 ;j<=i;j++){ f[i][j] = f[i - 1][j] + f[i - 1][j - 1]; if (pre[s[i] - 'a'])f[i][j] -= f[pre[s[i] - 'a'] - 1][j - 1]; f[i][j] %= mod; } pre[s[i]-'a'] = i; } ll ans =f[n][m]; if(ans< 0 )ans +=mod ; cout<<ans<<endl; return 0; }