河北省赛

https://ac.nowcoder.com/acm/contest/7055

B-Icebound and Squence

思路:递归

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll quick(ll q,ll n,ll p){
    ll ans=1,base=q;
    while(n){
        if(n&1) ans=ans*base%p;
        base=base*base%p;
        n>>=1;
    }
    return ans;
}
ll solve(ll q,ll n,ll p){
    if(n==1) return q%p;
    else if(n%2==0) return (solve(q,n/2,p)+quick(q,n/2,p)*solve(q,n/2,p))%p;
    else return (solve(q,n/2,p)+quick(q,n/2,p)*solve(q,n/2,p)+quick(q,n,p))%p;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        ll q,n,p;
        cin>>q>>n>>p;
        cout<<solve(q,n,p)%p<<endl;
    }
    return 0; 
}

 

C-分治

思路:这道题看是小区间推大区间,就用的区间dp.

           状态转移方程:

if(k==j) dp[j][i+j-1]=min(dp[j][i+j-1],a[k]*(i-1)+dp[j+1][i+j-1]);
else if(k==j+i-1) dp[j][i+j-1]=min(dp[j][i+j-1],a[k]*(i-1)+dp[j][i+j-2]);
else dp[j][i+j-1]=min(dp[j][i+j-1],dp[j][k-1]+dp[k+1][i+j-1]+(i-1)*a[k]);//怕错,分的比较细

            其实就是j到i+j-1这个区间的时候,你需要暴力枚举假设从k处分开,而且小于距离i最优子空间都是已知的,于是描述一下就可以。

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll a[3100],dp[2100][2100];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        memset(dp,0x3f3f3f3f,sizeof(dp));
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        for(int i=1;i<=n;i++) dp[i][i]=0;
        for(int i=2;i<=n;i++){
            for(int j=1;j<=n-i+1;j++){
                for(int k=j;k<=j+i-1;k++){
                    if(k==j) dp[j][i+j-1]=min(dp[j][i+j-1],a[k]*(i-1)+dp[j+1][i+j-1]);
                    else if(k==j+i-1) dp[j][i+j-1]=min(dp[j][i+j-1],a[k]*(i-1)+dp[j][i+j-2]);
                    else dp[j][i+j-1]=min(dp[j][i+j-1],dp[j][k-1]+dp[k+1][i+j-1]+(i-1)*a[k]);
                }
            }
        }
        cout<<dp[1][n]<<endl;
    }
}

L-smart robot

思路:一道搜索的题目,不过你得知道搜到几位数就行,xx学长给了个式子:10^k < n*n*4^k(k表示深度)然后直接搜就行。

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int M=1e6+2;
int s[2100][2100],vis[2200000],n;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void dfs(int x,int y,int num,int step){
    if(step>=6) return ;
    vis[num]=1;
    for(int i=0;i<4;i++){
        int fx=x+dx[i];
        int fy=y+dy[i];
        if(fx<=n&&fx>=1&&fy>=1&&fy<=n){
            dfs(fx,fy,num*10+s[fx][fy],step+1);
        } 
    }
    return ;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>s[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            dfs(i,j,s[i][j],0);
        }
    }
    for(int i=0;i<=M;i++){
        if(!vis[i]){
            cout<<i<<endl;
            break;
        }
    }
    return 0;
}

J-舔狗

思路:由于边数只有一个环,从入度较少的点慢慢往前更新删除,就算拆了环也没有关系。

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring> 
using namespace std;
const int M=1e6+5;
int x,n,a[M],vis[M],in[M];
struct node{
    int u,v;//u为编号,v为入度
    bool friend operator<(node x,node y){
        return x.v>y.v;
    } 
};
void solve(){
    int ans=0;
    priority_queue<node>q;
    for(int i=1;i<=n;i++){
        q.push(node{i,in[i]});
    }
    while(!q.empty()){
        node cur=q.top();q.pop();
        if(vis[a[cur.u]]||vis[cur.u]) continue;
        ans+=2;
        vis[cur.u]=1;
        vis[a[cur.u]]=1;
        q.push(node{a[a[cur.u]],--in[a[a[cur.u]]]});
    }
    cout<<n-ans<<endl;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        in[a[i]]++;
    }
    solve();
    return 0;
}

 

posted @ 2020-08-14 16:05  清水仙  阅读(99)  评论(0编辑  收藏  举报