1. 程式人生 > >Codeforces Round #369 (Div. 2)

Codeforces Round #369 (Div. 2)

turn mes syn back 矩陣 efi 正向 oid res

A:水,直接遍歷就好了

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 20090717
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using
namespace std; const double g=10.0,eps=1e-12; const int N=3000+10,maxn=10000+10,inf=0x3f3f3f3f; string s[N]; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin>>n; for(int i=0;i<n;i++)cin>>s[i]; for(int i=0;i<n;i++) { if(s[i][0]==
O&&s[i][1]==O) { cout<<"YES"<<endl; s[i][0]=s[i][1]=+; for(int j=0;j<n;j++)cout<<s[j]<<endl; return 0; } if(s[i][3]==O&&s[i][4]==O) { cout<<"YES
"<<endl; s[i][3]=s[i][4]=+; for(int j=0;j<n;j++)cout<<s[j]<<endl; return 0; } } cout<<"NO"<<endl; return 0; } /******************** ********************/
A

B:一個矩陣裏只有一個0,找一個正整數填上去,使每行每列和兩個對角線之和相同

坑點:忘記判斷最後是正數的情況

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 20090717
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-12;
const int N=3000+10,maxn=10000+10,inf=0x3f3f3f3f;

string s[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    for(int i=0;i<n;i++)cin>>s[i];
    for(int i=0;i<n;i++)
    {
        if(s[i][0]==O&&s[i][1]==O)
        {
            cout<<"YES"<<endl;
            s[i][0]=s[i][1]=+;
            for(int j=0;j<n;j++)cout<<s[j]<<endl;
            return 0;
        }
        if(s[i][3]==O&&s[i][4]==O)
        {
            cout<<"YES"<<endl;
            s[i][3]=s[i][4]=+;
            for(int j=0;j<n;j++)cout<<s[j]<<endl;
            return 0;
        }
    }
    cout<<"NO"<<endl;
    return 0;
}
/********************

********************/
B

C:1到n每個為0的格子填充1到m的顏色,求連續區間有k個的最小權值填充情況

看了好久沒有一點思路= =, 然後發現居然是O(n^4)的dp。。

轉移方程:dp[i][j][k]代表從1到i已經填充好了,i是填j的顏色,有k個連續區間的最小權值

if(c[i]==0)dp[i][j][k]=min(hh,dp[i-1][j][k])+cost[i][j]
else dp[i][c[i]]][k]=min(dp[i-1][c[i]]][k],hh)
hh=dp[i-1][!j][k-1]

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-12;
const int N=100+10,maxn=10000+10,inf=0x3f3f3f3f;

int c[N],p[N][N];
ll dp[N][N][N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)cin>>c[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>p[i][j];
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
            for(int u=0;u<=k;u++)
                dp[i][j][u]=1e15;
    if(!c[1])
    {
        for(int i=1;i<=m;i++)dp[1][i][1]=p[1][i];
    }
    else dp[1][c[1]][1]=0;
    for(int i=2;i<=n;i++)
    {
        if(c[i]!=0)
        {
            for(int j=1;j<=m;j++)
            {
                for(int u=1;u<=i&&u<=k;u++)
                {
                    if(j==c[i])dp[i][c[i]][u]=min(dp[i][c[i]][u],dp[i-1][c[i]][u]);
                    else dp[i][c[i]][u]=min(dp[i][c[i]][u],dp[i-1][j][u-1]);
                }
            }
        }
        else
        {
            for(int j=1;j<=m;j++)
            {
                for(int u=1;u<=m;u++)
                {
                    for(int v=1;v<=k&&v<=i;v++)
                    {
                        if(j==u)dp[i][j][v]=min(dp[i][j][v],dp[i-1][j][v]+p[i][j]);
                        else dp[i][j][v]=min(dp[i][j][v],dp[i-1][u][v-1]+p[i][j]);
                    }
                }
            }
        }
    }
    ll ans=1e15;
    for(int i=1;i<=m;i++)
     //   cout<<dp[n][i][k]<<endl,
        ans=min(ans,dp[n][i][k]);
    if(ans>=1e15)cout<<-1<<endl;
    else cout<<ans<<endl;
    return 0;
}
/********************
if(c[i]==0)dp[i][j][k]=min(hh,dp[i-1][j][k])+cost[i][k]
else dp[i][j][c[i]]=min(dp[i-1][j][c[i]],hh)
hh=dp[i-1][j-1][!k]
2 2 2
0 0
1 2
2 1
********************/
C

D:給你一個數組,i從i到a【i】有一條邊,對於一個有向圖如果有環,那麽我們叫他混亂的,要求所有翻轉邊的情況來使得該圖不混亂

題解:em首先可以註意到,該圖中的環一定是簡單環,而且每個聯通塊一定只有一個環,然後我們分別考慮每一個環(n個點),我們一定有2^n-2種翻轉情況,因為需要排除正向環和反向環的情況,然後對於不是環的邊,分別乘上去就好了

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-12;
const int N=200000+10,maxn=10000+10,inf=0x3f3f3f3f;

vector<int>v[N];
int a[N],pre[N];
int sz,en,be;
void dfs(int u,int f)
{
  //  cout<<u<<" "<<f<<endl;
    pre[u]=f;sz++;
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(x==f)continue;
        if(!pre[x])dfs(x,u);
        else
        {
            be=u;en=x;
        }
    }
}
ll quick(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        v[i].pb(a[i]);
        v[a[i]].pb(i);
    }
    ll ans=1;
    for(int i=1;i<=n;i++)
    {
        if(!pre[i])
        {
            sz=en=be=0;
            dfs(i,n+1);
     //       cout<<en<<" "<<be<<endl;
            if(en!=0)
            {
                int res=1;
                for(int p=en;p!=be;p=pre[p])res++;
                ans=ans*(quick(2,res)-2)%mod*quick(2,sz-res)%mod;
            }
            else ans=ans*quick(2,sz)%mod;
        }
    }
    cout<<ans<<endl;
    return 0;
}
/********************
5
2 3 1 5 4
********************/
D

E。。。待補

Codeforces Round #369 (Div. 2)