iwtgm-34
Educational Codeforces Round 159 (Rated for Div. 2)
A.
只要有0就是yes
因为若只有0,显然满足条件
若0和1都有,一定会有01相邻的情况,我们插入0后,仍有01相邻的情况,即我们可以无限+0,那么最后0的个数一定可以大于1
void solve() {
int n;cin>>n;
string s;cin>>s;
int cnt_0=0,cnt_1=0;
for(int i=0;i<s.size();i++){
if(s[i]=='0')cnt_0++;
else cnt_1++;
}
if(cnt_0&&cnt_1||cnt_0){
cout<<"YES"<<endl;
}
else cout<<"NO"<<endl;
}
B.
这种题思路容易出,但代码实现还是有点东西
#define int long long
void solve() {
int n, P, l, t;
cin >> n >> P >> l >> t;
int x = (n + 6) / 7;
// debug1(x);
int s = (x / 2) * (l + t * 2);
int ss = s + (x % 2) * (l + t);
int d = (l + t * 2);
if(s >= P){
cout << n - (P + d - 1) / d << endl;
}
else if(ss >= P){
cout << n - (x + 1) / 2 << endl;
}
else {
P -= ss;
int ans = (x + 1) / 2 + (P + l - 1) / l;
cout << n - ans << endl;
}
}
C.
想错的点是a(n+1)可以比a(n)小
#define int long long
void solve() {
int n;
cin >> n;
vector<int> a(n);
set<int> st;
for(auto &i : a) {
cin >> i;
st.insert(i);
}
vector<int> ans;
sort(a.begin(), a.end());
int mx = a.back();
for(auto i : a) {
if(mx - i != 0)
ans.push_back(mx - i);
}
if(!ans.size()) {
cout << 1 << endl;
return ;
}
int gc = ans[0];
for(int i = 1; i < ans.size(); i++) {
gc = __gcd(gc, ans[i]);
}
int res = 0;
for(int i = 1; i <= n; i++) {
if(!st.count(mx - gc * i)) {
res = i;
break;
}
}
if(res == 0)res = n;
for(auto i : ans) {
res += i / gc;
}
cout << res << endl;
}
D.
思路一直绕在点中心转换,其实不用
就按它题意,算偏移量,然后去二分查找是否存在
#define x first
#define y second
#define pt pair<int,int>
void solve() {
int n,q;cin>>n>>q;
string s;cin>>s;
vector<pt>pos(n+1);
for(int i=0;i<n;i++){
pos[i+1].x=pos[i].x+(s[i]=='R')-(s[i]=='L');
pos[i+1].y=pos[i].y+(s[i]=='U')-(s[i]=='D');
}
map<pt,vector<int>>mp;
for(int i=0;i<=n;i++)mp[pos[i]].push_back(i);
auto check=[&](pt p,int l,int r){
if(!mp.count(p))return false;
auto it= lower_bound(mp[p].begin(),mp[p].end(),l);
return it!=mp[p].end()&&*it<=r;
};
while(q--){
int x,y,l,r;cin>>x>>y>>l>>r;
int nx=pos[r].x+pos[l-1].x-x,ny=pos[r].y+pos[l-1].y-y;
bool f=check({x,y},0,l-1)|check({nx,ny},l,r-1)|check({x,y},r,n);
cout<<(f?"YES":"NO")<<endl;
}
}
E.
用字典树就可以很好地解决了
using ll = long long;
using pii = pair<int, int>;
using vint = vector<int>;
using vpo = vector<pii>;
vector<string> s(1000006);
int trie[1000006][26],cnt[1000006][26], tot = 0;
void insert(string str) {
int p = 0;
for (auto& c : str) {
int ch = c - 'a';
if (trie[p][ch] == 0)trie[p][ch] = ++tot;
++cnt[p][ch];
p = trie[p][ch];
}
}
ll que(string str) {
int p = 0; ll ret = 0;
for (int i = str.size() - 1; i >= 0; i--) {
int ch = str[i] - 'a';
ret += cnt[p][ch];
p = trie[p][ch];
if (p == 0)break;
}
ll size = str.size();
return ret;
}
int main(void)
{
IOS;
int n; cin >> n;
ll sumlen = 0;
for (int i = 1; i <= n; i++) {
cin >> s[i];
insert(s[i]);
sumlen += s[i].size();
}
ll ans=sumlen* 2 * n;
for (int i = 1; i <= n; i++) {
ans -= que(s[i])*2;
}
cout << ans << endl;
}
F.
浅学下异或线性基
异或性质:
若a\(\bigoplus\)b\(\bigoplus\)c=0,则a\(\bigoplus\)b=c
若a\(\bigoplus\)b=c,则a\(\bigoplus\)c=b
异或线性基:若集合a中的每一个数都能用集合b中的若干个(可为0个)数按位异或得出,
且集合b是满足上述要求的元素个数最少的集合,那么称b是a的一个异或线性基
a[]储存所有的线性基
a[i]表示线性基中(先出现的)最高位为i的元素(唯一,就是说这一位为1就标志着这个数,其他数都被抵消)(后面的这一位会被抵消,后面会再说)
如果a[i]=0,表示线性基里还没有最高位为第i位的元素
将元素x插入线性基里,从高到低枚举x的每一个二进制位
假设枚举到第i位
如果a[i]=0,那就说明x的第i位不能被目前线性基里的数异或出,所以必须把x插入线性基,即a[i]=x;
否则,我们要把x的第i位用a[i]消掉,也就是x^a[i].(这就是为什么我们要让线性基内任意两个数的二进制最高位不同,因为这样才能起到消位的作用)
#define int long long
int n;
int a[51];
void get_lb(int x){
for(int i=50;i>=0;i--){
if((x&(1ll<<i))==0)continue;
if(a[i]>0)x^=a[i];
else{
a[i]=x;
return ;
}
}
}
void solve() {
cin>>n;
for(int i=1;i<=n;i++){
int k;cin>>k;
get_lb(k);
}
}