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!−2n−1
歪门邪道(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[i−2]+f[i−3]+...+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
n≤m,对于
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
如果i
和j
能过转移则转移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;
}
要加油哦~