比賽連結:https://codeforces.com/contest/2036
A. Quintomania
思路:資料範圍小+題目清晰,題目要求左右兩個數之差絕對值不等於\(5\)或這不等於\(7\),直接暴力即可,應該不會有人不知到內建函式\(abs\)吧
#include<iostream>
#include<queue>
#include<map>
#include<set>A~F
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
ll pd=0;
ll o;
for(ll i=1;i<=n;i++)
{
ll x;
cin>>x;
if(i>=2)
{
if(abs(o-x)==5||abs(o-x)==7)
{
o=x;
continue;
}
pd=1;
}
o=x;
}
if(pd)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
}
B. Startup
思路:一開始看成選(總瓶子大於\(k\))\(k\)個瓶子放在\(n\)個貨架上,然後貨架上的牌子只能是同一種,感覺很難。
隨後發現看錯了,是總共有\(k\)個瓶子,然我放在\(n\)個貨架上,且品牌得一樣,於是直接貪心的把所有品牌對應的值進行累積,
然後進行排序,從大到小選取前\(min(n,牌子種類)\)個即可,本人為了方便直接用了優先對列
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n,k;
cin>>n>>k;
map<ll,ll>mp;
set<ll>q;
priority_queue<ll>f;
for(ll i=1;i<=k;i++)
{
ll x,y;
cin>>x>>y;
mp[x]+=y;
q.insert(x);
}
for(auto j:q)
{
f.push(mp[j]);
}
ll ans=0;
while(!f.empty())
{
ans+=f.top();
f.pop();
n--;
if(n==0)
break;
}
cout<<ans<<endl;
}
}
C. Anya and 1100
思路:對於一個字串有\(q\)次修改,問每次修改後是否存在\(1100\)字串
不妨想想,每次修改一個位置,最多會影響\(4\)個位置的可能,所以直接先暴力統計一開始的所有\(1100\)子串,然後每次修改進行區間\(1100\)變化統計
然後再修改原本的\(1100\)個數就可以了
賽事犯了個低階錯誤,一開始統計\(1100\)直接\(4\)個\(4\)個查了。···
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
string f;
cin>>f;
ll n=f.size();
ll q;
cin>>q;
ll ans=0;
f='0'+f;
for(ll i=1;i<=n-3;i++)
{
if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
ans++;
}
while(q--)
{
ll x;
char y;
cin>>x>>y;
if(n<4)
{
cout<<"NO"<<endl;
continue;
}
else
{
ll cnt=0;
//cout<<n<<endl;
for(ll i=x-3;i<=x;i++)
{
if(i>=1&&i+3<=n)
{
if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
cnt++;
}
}
f[x]=y;
ll uo=0;
for(ll i=x-3;i<=x;i++)
{
if(i>=1&&i+3<=n)
{
if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
uo++;
}
}
//cout<<cnt<<endl;
uo-=cnt;
ans+=uo;
if(ans>0)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}
}
}
D. I Love 1543
思路:其實就是模擬下字串有沒有\(1543\),如何模擬?
首先外圍走一圈順時針是很有格式規定的,於是考慮遞迴寫,然後終止條件可以畫畫,是目前最大行小於等於\(n/2\)或者目前最大列小於等於\(m/2\)
,然後每次縮一次上邊界和下邊界就可以了,統計的話為了方便直接重新進行字串加和,然後再倍增一下,列舉\(0到size()/2-1\)最為第一個字元就可以了,注意防止越界哦
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
string f[4000];
ll n,m;
ll ans=0;
void ck(ll x,ll y,ll s,ll p)
{
if(x<=n/2||y<=m/2)
return ;
string u="";
for(ll j=p;j<=y;j++)
{
u+=f[s][j];
}
for(ll j=s+1;j<=x;j++)
{
u+=f[j][y];
}
for(ll j=y-1;j>=p;j--)
{
u+=f[x][j];
}
for(ll i=x-1;i>=s+1;i--)
{
u+=f[i][p];
}
//cout<<u<<endl;
ll k=u.size()-1;
u+=u;
for(ll i=0;i<=k;i++)
{
if(i+3<=(ll)u.size()-1&&u[i]=='1'&&u[i+1]=='5'&&u[i+2]=='4'&&u[i+3]=='3')
{
ans++;
}
}
//cout<<ans<<endl;
ck(x-1,y-1,s+1,p+1);
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
//ll n,m;
cin>>n>>m;
for(ll i=1;i<=n;i++)
{
cin>>f[i];
f[i]='0'+f[i];
}
ans=0;
ck(n,m,1,1);
cout<<ans<<endl;
}
}
E. Reverse the Rivers
思路:\(n*k<=10^5\),所以在\(main\)函式內定義二維陣列,然後先按照題目要求進行處理或之和(兩個數之或一定不變或者增加,所以或之和是不遞減的,具有單調性),然後再用一個陣列以列為第一維行為第二維統計每行對應的數,然後有\(q\)次詢問,但是注意\(m<=10^5\),所以其實也就最多有\(m\)個約束。因為題目要求找到合理的最小序號,所以要用\(l,r\)雙指標進行區間維護,對於\(<\),可以用\(lower_bound\)找到第一個大於等於\(y\)的行\(c\),然後\(c--\),取\(r=min(r,c)\),對於\(>\),可以用\(upper_bound\)直接找到對應的行\(c\),然後取\(l=max(l,c)\)即可,如果\(l>r\),輸出\(-1\),否則輸出\(l\)
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
ll t;
t=1;
while(t--)
{
ll n,k,q;
cin>>n>>k>>q;
ll a[n+5][k+5];
for(ll i=0;i<=n;i++)
{
for(ll j=0;j<=k;j++)
{
a[i][j]=0;
}
}
for(ll i=1;i<=n;i++)
{
for(ll j=1;j<=k;j++)
{
cin>>a[i][j];
}
}
//cout<<a[0][1]<<endl;
ll b[k+5][n+5]={0};
for(ll j=1;j<=k;j++)
{
for(ll i=1;i<=n;i++)
{
a[i][j]=(a[i][j]|a[i-1][j]);
b[j][i]=a[i][j];
//cout<<a[i][j]<<endl;
}
}
//cout<<b[1][2]<<endl;
while(q--)
{
ll m;
cin>>m;
ll l=1,r=n;
for(ll i=1;i<=m;i++)
{
ll x,y;
char f;
cin>>x>>f>>y;
if(f=='<')
{
ll u=lower_bound(b[x]+1,b[x]+1+n,y)-b[x];
u--;
r=min(r,u);
}
else
{
ll u=upper_bound(b[x]+1,b[x]+1+n,y)-b[x];
l=max(l,u);
}
}
if(l>r)
{
cout<<-1<<endl;
}
else
cout<<l<<endl;
}
}
}
F. XORificator 3000
思路:賽時沒考慮r<k時直接輸出答案,一直WA2
其實對於一個從1開始的連續區間的異或和,其答案是有規律的
規律如下:
當\(n%4==0\):
\(f(1,n)=n\)
當\(n%4==1\):
\(f(1,n)=1\)
當\(n%4==2\):
\(f(1,n)=n+1\)
當\(n%4==3\):
\(f(1,n)=0\)
顯然對於\(f(l,r)\)有\(f(l,r)=f(1,r)^f(1,l-1)\)
隨後如何處理不合理答案
其實容易發現對於\(2^i\)乘連續數的答案的異或之和會等於連續的數的異或之和乘以\(2^i\)
所以解決了\(2^i\)的問題然後是對於\(k\),他其實一直在異或自己,如果異或了自己偶數次,則為\(0\),否則為本身,這個的次數奇偶性等於區間\(2^i*b+k\),\(b\)的可能個數的奇偶性
最後處理好是否異或\(k\)就行了,注意特判情況\(r<k\)哦
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll __int64
#define lowbit(x) (x & -x)
#define endl "\n"// 互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll ck(ll r)
{
if(r%4==0)
{
return r;
}
else if(r%4==1)
{
return 1;
}
else if(r%4==2)
{
return r+1;
}
else
{
return 0;
}
}
int main()
{
ll t;
cin>>t;
while(t--)
{
ll l,r,f,k;
cin>>l>>r>>f>>k;
ll ans=0;
ans=(ck(r)^ck(l-1));
if(r<k)
{
cout<<ans<<endl;
continue;
}
//cout<<ans<<endl;
ll u=1<<f;
ll l1=(l-k)/u+((l-k)%u>0);
ll r1=(r-k)/u;
ll op;
op=ck(r1)^ck(l1-1);
op*=u;
ans^=op;
if((r1-l1+1)%2==0)
cout<<ans<<endl;
else
{
cout<<(ans^k)<<endl;
}
}
}