D.I Love 1543
思路:
把每一层的拿出看有没有1543,这里可以用dfs,也可以用4次循环,每一边一次。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//pair<ll,ll> fx[4]={{-1,0},{0,1},{1,0},{0,-1}};
ll an[4]={1,5,4,3};
void solve(){
ll n,m;cin>>n>>m;
vector<string> v(n);
for(ll i=0;i<n;i++)cin>>v[i];
vector<ll> a;
vector<vector<bool>> vis((n),vector<bool> (m,false));
auto dfs=[&](auto &&dfs,ll x,ll y,ll c)->void{
if(vis[x][y])return;
a.push_back(v[x][y]-'0');
vis[x][y]=true;
ll tx,ty;
tx==x;
ty=y;
if(x==c){
if(y==m-1-c){
tx++;
}else{
ty++;
}
}else if(x==n-1-c){
if(y==c){
tx--;
}else{
ty--;
}
}else if(y==c){
if(x==c){
ty++;
}else{
tx--;
}
}else if(y==m-1-c){
if(x==n-1-c){
ty--;
}else{
tx++;
}
}
if(vis[tx][ty])return;
return;
};
auto f=[&]()->ll{
ll res=0;
ll idx=0;
for(ll i=0;i<a.size();i++){
if(a[i]==1){
idx=i;break;
}
}
ll cnt=0;
for(ll i=idx,j=0;i<idx+a.size();i++){
ll t=i%a.size();
if(a[t]==an[j]){
j++;
}else{
if(a[t]==1){
j=1;
}else{
j=0;
}
}
if(j==4){
res++;
j=0;
}
}
return res;
};
ll ans=0;
for(ll c=0;c<min(n/2,m/2);c++){
a.clear();
dfs(dfs,c,c,c);
ans+=f();
}
cout<<ans<<endl;
return;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll _;cin>>_;
while(_--)solve();
}
E.Reverse the Rivers
思路:
首先我们要知道对于或运算它的结果一定>=前一个数。然后我们就可以先初始化一个范围1~n,然后对于问一次询问通过二分得到新的范围然后求交集。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
int n,k,q;cin>>n>>k>>q;
vector<vector<int>> a(n+1,vector<int> (k+1));
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++)cin>>a[i][j];
}
for(int i=1;i<=k;i++){
for(int j=1;j<=n;j++){
a[j][i]=a[j][i]|a[j-1][i];
}
}
auto f=[&](int &l,int &r,int tl,int tr)->void{
if(l>r){
return;
}
if(r<tl){
l=1,r=-1;
return;
}
if(l>tr){
l=1,r=-1;
return;
}
l=max(l,tl);
r=min(r,tr);
return;
};
while(q--){
int m;cin>>m;
int ans_l=1,ans_r=n;
for(int i=0;i<m;i++){
int j;char o;int c;
cin>>j>>o>>c;
int l=1,r=n;
int t=0;
if(o=='>'){
while(l<=r){
int mid=(l+r)/2;
if(a[mid][j]>c){
t=mid;
r=mid-1;
}else{
l=mid+1;
}
}
if(t!=0){
f(ans_l,ans_r,t,n);
}else{
ans_l=1;
ans_r=-1;
}
}else{
while(l<=r){
int mid=(l+r)/2;
if(a[mid][j]<c){
t=mid;
l=mid+1;
}else{
r=mid-1;
}
}
if(t!=0){
f(ans_l,ans_r,1,t);
}else{
ans_l=1;
ans_r=-1;
}
}
}
if(ans_l>ans_r){
cout<<-1<<endl;
}else{
cout<<ans_l<<endl;
}
}
return;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
solve();
}
F.XORificator
思路:
我们要清楚对于对于二进制异或的结果,当前位置1为奇数个时那么最终结果为1,否则为0。所以我们只需要把每一位的1的个数求出来即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f1(ll cnt){
return (ll)1<<cnt;
}
ll f2(ll cnt){
return cnt/2;
}
void solve(){
ll l,r,i,k;cin>>l>>r>>i>>k;
if(i==0){
cout<<0<<endl;return;
}
vector<ll> cnt(61,0);
for(ll j=0;j<60;j++){
ll t=f1(j+1);
cnt[j]+=(r+1)/t*f2(t)+max((r+1)%t-f2(t),(ll)0);
}
for(ll j=0;j<60;j++){
ll t=f1(j+1);
cnt[j]-=l/t*f2(t)+max(l%t-f2(t),(ll)0);
}
for(ll j=0;j<60;j++){
if(j<i){
if(k&f1(j)){
ll t=f1(i);
cnt[j]-=(r+1)/t+(((r+1)%t)>k?1:0);
}
}else{
ll t=f1(j+1);
cnt[j]-=(r+1)/t*f2(t)/f1(i)+max((r+1)%t-f2(t),(ll)0)/f1(i)+((max((r+1)%t-f2(t),(ll)0)%f1(i))>k?1:0);
}
}
for(ll j=0;j<60;j++){
if(j<i){
if(k&f1(j)){
ll t=f1(i);
cnt[j]+=l/t+((l%t)>k?1:0);
}
}else{
ll t=f1(j+1);
cnt[j]+=l/t*f2(t)/f1(i)+max(l%t-f2(t),(ll)0)/f1(i)+((max(l%t-f2(t),(ll)0)%f1(i))>k?1:0);
}
}
ll ans=0;
for(ll j=0;j<60;j++){
if(cnt[j]%2){
ans+=f1(j);
}
}
cout<<ans<<endl;
return;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll _;cin>>_;
while(_--)solve();
}