关闭

Codeforces Round #369 (Div. 2) 题解

153人阅读 评论(0) 收藏 举报
分类:

【A. Bus to Udayland】http://www.codeforces.com/contest/711/problem/A

【题意】公交车上有些位置能做,有些不能坐,问是否有两个相邻的位置。

【解题方法】找到并排的2个0就行了。

【AC代码】

#include <bits/stdc++.h>
using namespace std;
int n;
char s[1010][10];
int main()
{
    cin>>n;
    for(int i=0; i<n; i++) cin>>s[i];
    bool flag=false;
    for(int i=0; i<n; i++)
    {
        if(s[i][0]=='O'&&s[i][1]=='O')
        {
            flag=true;
            s[i][0]=s[i][1]='+';
            break;
        }
        if(s[i][3]=='O'&&s[i][4]=='O')
        {
            flag=true;
            s[i][3]=s[i][4]='+';
            break;
        }
    }
    if(flag){
        puts("YES");
        for(int i=0; i<n; i++)printf("%s\n",s[i]);
    }
    else{
        puts("NO");
    }
}

【B. Chris and Magic Square】http://www.codeforces.com/contest/711/problem/B

【题意】一个n*n(n<=500)的矩形中有一个格子为空,问是否能填上某个数,使得每行每列以及主对角线之后均相等。

【解题方法】n=1特判。n>=2找出某个可能合法的解,填入后再验证一下。 数据范围爆int啦。

【AC 代码】

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e5+10;
LL a[550][550];
LL row[550];
LL col[550];
set<LL>s;
int c,r;
int main()
{
    int n;
    cin>>n;
    s.clear();
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
            scanf("%I64d",&a[i][j]);
            if(a[i][j] == 0){
                r = i,c = j;
            }
        }
    }
    if(n == 1){
        printf("1\n");
        return 0;
    }
    LL sum = 0;
    for(int i = 1;i <= n;i++){
        if(i != r){
            for(int j = 0;j <= n;j++){
                sum += a[i][j];
            }
            break;
        }
    }
    for(int i  = 1;i <= n;i++){
        sum -= a[r][i];
    }
    a[r][c] = sum;
    LL sum1 = 0,sum2 = 0;
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
            col[i] += a[i][j];
            row[i] += a[j][i];
        }
        sum1 += a[i][i];
        sum2 += a[i][n-i+1];
    }
    s.insert(sum1);
    s.insert(sum2);
    for(int i = 1;i <= n;i++){
        s.insert(col[i]);
        s.insert(row[i]);
    }
    if(s.size() > 1){
        puts("-1");
    }
    else{
        if(sum>0) cout<<sum<<endl;
        else puts("-1");
    }
    return 0;
}

【C. Coloring Trees】http://www.codeforces.com/contest/711/problem/C

【题意】有n棵树排成一列,一共有m种颜料,有些树被涂了颜色,有些树没有。可以花费a[i][j]的代价给第i棵树涂上j的颜色。问给每棵树涂上颜色后,将树恰好分成k段的最小花费。(连续颜色相同的最长区间为一段)n,m,k<=100【解题方法】n^4的dp显而易见啦。好像有n^3的,不过n才100,谁便搞啦。

【AC 代码】O(n^4)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL inf = 1e18;
const int maxn=110;
LL a[maxn],b[maxn][maxn],dp[maxn][maxn][maxn];
int n,m,k;
int main()
{
    cin>>n>>m>>k;
    for(int i=1; i<=n; i++) cin>>a[i];
    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            cin>>b[i][j];
        }
    }
    memset(dp,0x3f,sizeof(dp));
    if(!a[1]) for(int i=1; i<=m; i++) dp[1][i][1]=b[1][i];
    else dp[1][a[1]][1]=0;
    for(int i=1; i<n; i++){
        for(int j=1; j<=m; j++){
            for(int l=1; l<=k; l++){
                if(a[i+1]==0){
                    for(int r=1; r<=m; r++){
                        if(j==r) dp[i+1][r][l]=min(dp[i+1][r][l],dp[i][j][l]+b[i+1][r]);
                        else dp[i+1][r][l+1]=min(dp[i+1][r][l+1],dp[i][j][l]+b[i+1][r]);
                    }
                }
                else{
                    for(int r=1; r<=m; r++){
                        if(j==a[i+1]) dp[i+1][j][l]=min(dp[i+1][j][l],dp[i][j][l]);
                        else dp[i+1][a[i+1]][l+1]=min(dp[i+1][a[i+1]][l+1],dp[i][j][l]);
                    }
                }
            }
        }
    }
    LL ans=inf;
    for(int i=1; i<=m; i++){
        ans=min(ans,dp[n][i][k]);
    }
    if(ans==inf) ans=-1;
    printf("%I64d\n",ans);
    return 0;
}

【D. Directed Roads】http://www.codeforces.com/contest/711/problem/D

【题意】有n个点,给定一个数组a[i](≠i),表示有一条i-->a[i]的有向边。可以将某些有向边的方向翻转,因此共有2^n的方案。问这些方案中有多少种方案使得所形成的图不含有环。n<=2*10^5

【解题方法】由于一共只有n条边,整个图相当于被分成了若干个联通块,且每个联通块内有且只有一个环。若某个连通块中有i个点,存在一个点数为j的环,那么其对答案的贡献为2^(i-j) * (2^j-2)

【AC 代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int maxn = 2e5+5;
int p[maxn],c[maxn],clk[maxn];
LL powmod(int x)
{
    LL res=1;
    while(x--)
    {
        res<<=1;
        res%=mod;
    }
    return res;
}
int main()
{
    int n,cnt=0;
    cin>>n;
    for(int i=1; i<=n; i++) cin>>p[i];
    int num=n;
    LL ans=1;
    for(int i=1; i<=n; i++){
        if(!c[i])
        {
            c[i]=i;
            clk[i]=++cnt;
            int x=i;
            while(1)
            {
                x=p[x];
                if(c[x])
                {
                    if(c[x]==i){
                        int t=cnt-clk[x]+1;
                        ans=ans*(powmod(t)-2)%mod;
                        ans=ans%mod;
                        num-=t;
                    }
                    break;
                }
                else{
                    c[x]=i;
                    clk[x]=++cnt;
                }
            }
        }
    }
    ans=ans*powmod(num);
    ans%=mod;
    if(ans<0) ans+=mod;
    cout<<ans<<endl;
    return 0;
}

【E. ZS and The Birthday Paradox】点击打开链接

【题意】假设一年有2^n天,问k个小朋友中有两个小朋友生日相同的概率。假设该概率约分后为 p / q ,输出p , q对1000003取模的解。n , k <= 10^18。

【解题方法】参见http://www.cnblogs.com/rpSebastian/p/5821057.html

【解题方法】若k > 2^n 则答案为1 / 1 , 否则答案为 1 - A(2^n,k) / (2^n)^k ,可以发现分子与分母的gcd必定为2^i。计算A(2^n,k)=(2^n) * (2^n-1) * ... * (2^n-k+1)含多少个因子2,相当于计算0~k-1以及2^n。求出gcd后,就可以暴力计算分子,分母对p取模后的结果,再乘上gcd的逆元。

【AC 代码】

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=1e6+3;
LL powmod(LL a,LL n)
{
    LL res=1;
    while(n)
    {
        if(n&1) res=res*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return res;
}
int main()
{
    LL n,k;
    scanf("%I64d%I64d",&n,&k);
    if(n<=62&&k>(1LL<<n)){
        printf("1 1\n");
        return 0;
    }
    //这里想了很久啊,悲伤
   LL num=0;
    for(LL i=k-1; i; i>>=1){
        num+=i/2;
    }
    //cout<<num<<endl;
    LL a=powmod(2,n),b=1;
    for(LL i=1; i<=k-1; i++)
    {
        LL temp=(a-i+mod)%mod;
        b=b*temp%mod;
        if(temp==0) break;
    }
    //cout<<b<<endl;
    //cout<<a<<" "<<b<<endl;
    LL inv=powmod(powmod(2,num),mod-2);
    a=powmod(a,k-1);
    a=a*inv%mod;
    b=b*inv%mod;
    b=(a-b+mod)%mod;
    printf("%I64d %I64d\n",b,a);
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:263016次
    • 积分:14174
    • 等级:
    • 排名:第896名
    • 原创:1191篇
    • 转载:13篇
    • 译文:0篇
    • 评论:61条
    文章分类