Codeforces Round #663 (Div. 2)

2020/8/9晚上断网了,本来不想打就顺便看看题目,发现能做几个,然后就交了。(做完1、2两题才敢交)最终做了3个题tcl。

A - Suborrays

脑筋急转弯题目。位运算OR运算结果只会变大不会变小,直接正序输出就可

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    IO;
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) cout<<i<<" ";
        cout<<endl;
    }
    return 0;
}

B - Fix You

这个题感觉比A还容易写出来。直接保证最后一行和最后一列出不去就行。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#define debug(x) cout<<#x<<": "<<x<<" "
#include<iostream>
#include<algorithm>
using namespace std;
const int N=110;
int n,m;
char g[N][N];
int main()
{
    IO;
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>g[i]+1;
        int res=0;
        for(int i=1;i<n;i++)
            if(g[i][m]!='D') res++;
        for(int j=1;j<m;j++)
            if(g[n][j]!='R') res++;
        cout<<res<<endl;
    }
    return 0;
}

C - Cyclic Permutations

正解:直接输出 n ! − 2 n − 1 n!-2^{n-1} n!2n1
歪门邪道(wtcl):无环转化一下就是两个数之间不能有一个数比他俩都小
于是尝试构造:对于1 2 3 4…n我们发现原序列满足,逆序也满足。
1 (3 4…n ) 2 只要括号里面没有环,原序列没有环
1 2 (4 … n) 3 同样只要括号里面没有环,原序列没有环

只要正序无环那么逆序也无环
于是 f [ i ] = 2 × ( f [ i − 2 ] + f [ i − 3 ] + . . . + f [ 1 ] ) + 2 f[i]=2×(f[i-2]+f[i-3]+...+f[1])+2 f[i]=2×(f[i2]+f[i3]+...+f[1])+2(+2是1 2 3…n和n … 3 2 1)
因此答案是 n ! − f [ n ] n!-f[n] n!f[n]

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1000010,mod=1e9+7;
ll f[N];
int main()
{
    IO;
    int n;
    cin>>n;
    ll a=1;
    for(int i=1;i<=n;i++) a=a*1ll*i%mod;//预处理 n!
    f[1]=1,f[2]=3;//f[2]=2, f[2]=f[2]+f[1]=3 前缀和
    for(int i=3;i<=n;i++)
    {
        f[i]=(2*f[i-2]%mod+2)%mod;
        f[i]=(f[i]+f[i-1])%mod;
    }
    cout<<((a-f[n]+f[n-1])%mod+mod)%mod<<endl;//前缀和
    return 0;
}

大佬:这种规律题目可以直接猜结论

D - 505

这题快写成模拟了注意 n ≤ m n \leq m nm,对于 n > 3 n>3 n>3一定不符合直接输出-1。( n > 3 n>3 n>3考虑 2 × 2 2×2 2×2 4 × 4 4×4 4×4,一个 4 × 4 4×4 4×4肯定有四个 2 × 2 2×2 2×2因为 2 × 2 2×2 2×2都是奇数个1,因而 4 × 4 4×4 4×4中一定有偶数个1)自己就想到这。
大神题解
暴力枚举每一列的状态状态压缩
状态表示:①集合:f[i][j]表示第i列的状态是j并且符合题意的集合②属性:最小值
状态计算:枚举上一列的状态k如果ij能过转移则转移f[i][j]=min(f[i][j],f[i-1][k]+calc(now^j)
now是原数组该列的状态j是枚举的状态,由now->j花费的代价为calc(now^j)

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#define debug(x) cout<<#x<<": "<<x<<" "
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=1000010;
int n,m;
int a[5][N];
bool ok[10][10];
int f[N][10];
int lowbit(int x)
{
    return x&-x;
}
int calc(int x)
{
    int res=0;
    while(x)
    {
        x-=lowbit(x);
        res++;
    }
    return res;
}
void init(int n)
{
    for(int i=0;i<1<<3;i++)
        for(int j=0;j<1<<3;j++)
        {
            int cnt1[3];
            cnt1[0]=cnt1[1]=cnt1[2]=0;
            for(int k=0;k<3;k++)
            {   
                if(i>>k&1) cnt1[k]++;
                if(j>>k&1) cnt1[k]++;
            }
            bool flag=1;
            for(int k=0;k<n-1;k++)//注意n-1
                if((cnt1[k]+cnt1[k+1])%2==0) flag=0;
            if(flag) ok[i][j]=1;
        }
}
int main()
{
    //OI;这个东西和scanf混用会出问题!!!
    cin>>n>>m;
    if(n>=4) return printf("-1\n"),0;
    if(n==1) return printf("0\n"),0;//神仙写法,学习了
    init(n);//预处理合法转移的状态 i j
    for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++) scanf("%1d",&a[i][j]);
    memset(f,0x3f,sizeof f);
    for(int i=0;i<1<<n;i++) f[0][i]=0;
    for(int i=1;i<=m;i++)
    {
        int now=a[1][i]+a[2][i]*2+a[3][i]*4;
        for(int j=0;j<1<<n;j++)
            for(int k=0;k<1<<n;k++)
                if(ok[j][k]) f[i][j]=min(f[i][j],f[i-1][k]+calc(now^j));
    }
    int res=0x3f3f3f3f;
    for(int i=0;i<1<<n;i++) res=min(res,f[m][i]);
    printf("%d\n",res);
    return 0;
}

要加油哦~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值