2019ICPC南京-CH

比赛:https://qoj.ac/contest/1321

C

定义dp[i][j][k]表示(i,j)为末尾,长度为k的路径的数量,注意>=4通通放到k=4的位置。按元素大小顺序计算dp,注意重复问题,例如1 2 3 4,dp[1][4][3]不应把2->3->4算上,dp[1][4][2]不应把3->4算上,虽然在这个1x4的矩阵里不影响结果,但是矩阵再复杂一点点就寄了。

解决方法就是,当上一个位置已经有上上个位置(即dp[lx][ly][2..4]有>0的元素,(lx,ly)是上一个位置),就不再拼接(lx,ly)->(x,y)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

ll n,m;
ll dp[1005][1005][5]; // 0-3长度为i 4长度>=4
ll vis[1005][1005][5]; // 0-3长度为i 4长度>=4
ll a[1005][1005];
ll P=1000000007LL;
ll nend[1005][1005];
map<ll,vector<pair<ll,ll>>> pos;
#define fi first
#define se second

ll dx[]={1,0,-1,0};
ll dy[]={0,1,0,-1};

#define inc(x,y) (x=(x+((y)%P))%P)

void solve(){
    cin>>n>>m;
    for(ll i=1;i<=n;++i){
        for(ll j=1;j<=m;++j){
            cin>>a[i][j];
            dp[i][j][1]=1;
            if(pos.find(a[i][j])==pos.end())pos[a[i][j]]=vector<pair<ll,ll>>(0);
            pos[a[i][j]].push_back({i,j});
        }
    }
    
    for(auto& p:pos){
        vector<pair<ll,ll>>& v=p.second; 
        for(auto& [x,y]:v){
            for(ll i=0;i<4;++i){
                ll nx=dx[i]+x; // lx
                ll ny=dy[i]+y; // ly
                if(nx<1||nx>n||ny<1||ny>m||a[nx][ny]!=a[x][y]-1)continue;
                nend[nx][ny]=1;
                ll ok=0;
                for(ll j=4;j>1;--j){
                    ll nj=min(j+1,4LL);
                    if(vis[nx][ny][j]){
                        inc(dp[x][y][nj],dp[nx][ny][j]);
                        ok=1;
                        vis[x][y][nj]=1;
                    }
                }
                if(ok==0){
                    inc(dp[x][y][2],dp[nx][ny][1]);
                    vis[x][y][2]=1;
                }
            }
        }
    }

    ll ans=0;
    for(ll i=1;i<=n;++i){
        for(ll j=1;j<=m;++j){
            if(nend[i][j]==0){
                inc(ans,dp[i][j][4]);
            }
            // cout<<"dp["<<i<<"]["<<j<<"][4]="<<dp[i][j][4]<<"\n";
        }
    }
    cout<<ans;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t=1;
    // cin>>t;
    while(t--)
        solve();

    return 0;
}

H

首先按最坏情况考虑,b和c都当作一个团伙,当a<=b+c时,bc团伙分出a个人组成小团体1,剩下的组成小团体2。小团体1假装一个人是公主,其他人当作自己是隔壁的哥们,然后对于王子来说,无论怎么问,小团体1这a个人和说真话那边的a个人不可能区分开。

a>b+c时,每次都问第三种问题,显然回复当中出现最多的那个就是答案,最多问2*(b+c)+1次。

特殊情况:a=1,b+c=0,这时候不需要问。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve(){
    ll a,b,c;
    cin>>a>>b>>c;
    if(b==0&&c==0&&a==1)cout<<"YES\n"<<0;
    else if(a>b+c)cout<<"YES\n"<<2*(b+c)+1;
    else cout<<"NO";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t=1;
    // cin>>t;
    while(t--)
        solve();

    return 0;
}
posted @ 2026-03-27 19:45  TimeLimit  阅读(4)  评论(0)    收藏  举报