第一次kickstart体验很迷,感觉题目比想象的简单了ORZ,但是还是发现了自己的很多不足,继续加油吧
A
暴力
写了trie树,用总方案数遍历减去所有不可行方案数即可,不写trie树应该也能过。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<set>
#include<math.h>
#include<queue>
#include<map>
#include<stack>
#include<deque>
#define go(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define ll long long
#define MOD 1000000007
#define N 10005
#include<fstream>
using namespace std;
ll pow2[55],ans;
char s[500];
int cnt;
void init(){
pow2[0]=1;
for (int i=1;i<=50;i++){
pow2[i]=pow2[i-1]*2;
//cout<<pow2[i]<<endl;
}
return;
}
struct node{
int t0,t1;
bool istail;
}t[20005];
void trie(){
int root=0;
int len=strlen(s);
for (int i=0;i<len;i++){
if (t[root].istail) break;
if (s[i]=='R'){
if (t[root].t1==0) t[root].t1=++cnt;
root=t[root].t1;
}
else{
if (t[root].t0==0) t[root].t0=++cnt;
root=t[root].t0;
}
}
t[root].istail=true;
}
void dfs(int now, int dep){
if (t[now].istail){
ans-=pow2[dep];
return;
}
if (t[now].t1!=0) dfs(t[now].t1,dep-1);
if (t[now].t0!=0) dfs(t[now].t0,dep-1);
return;
}
int main(){
init();
int T,n,p;
ofstream fout;
ifstream fin;
fin.open("a.in");
fout.open("a.out");
fin>>T;
for (int ca=1;ca<=T;ca++){
memset(t,0,sizeof(t));
fin>>n>>p;
ans=pow2[n];
cnt=0;
for (int i=1;i<=p;i++){
fin>>s;
trie();
}
dfs(0,n);
fout<<"Case #"<<ca<<": "<<ans<<endl;
}
}
B
尺取暴力
任意连续的长度为的墙都可以取到,直接求最优解即可
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<set>
#include<math.h>
#include<queue>
#include<map>
#include<stack>
#include<deque>
#define go(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define ll long long
#define MOD 1000000007
#define N 10005
#include<fstream>
using namespace std;
char s[5000005];
int main(){
ofstream fout;
ifstream fin;
fin.open("b.in");
fout.open("b.out");
int T,n;
fin>>T;
for (int ca=1;ca<=T;ca++){
cout<<ca<<endl;
fin>>n;
int k=n/2+n%2;
ll ans,tmp=0;
fin>>s+1;
for (int i=1;i<=k;i++){
tmp+=(s[i]-'0');
}
ans=tmp;
for (int i=k+1;i<=n;i++){
tmp=tmp-(s[i-k]-'0')+(s[i]-'0');
ans=max(ans,tmp);
}
fout<<"Case #"<<ca<<": "<<ans<<endl;
}
}
C
数论
刚开始想推递推公式,推不出来,后来开始敲容斥的暴力算法,发现暴力算法改改就可以过large了
还是姿势水平不够吧,早早想一想就可以知道暴力的时间复杂度是了
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<set>
#include<math.h>
#include<queue>
#include<map>
#include<stack>
#include<deque>
#define go(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define ll long long
#define MOD 1000000007
#define N 100005
#include<fstream>
using namespace std;
ll F[2*N], Finv[2*N], inv[2*N],p[2*N];
void inn(){
p[0]=1;
for (int i=1;i<2*N;i++) p[i]=(p[i-1]*2)%MOD;
inv[1] = 1;
for(int i = 2; i < 2*N; i ++){
inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
}
F[0] = Finv[0] = 1;
for(int i = 1; i < 2*N; i ++){
F[i] = F[i-1] * 1ll * i % MOD;
Finv[i] = Finv[i-1] * 1ll * inv[i] % MOD;
}
}
ll comb(int n, int m){
if(m < 0 || m > n) return 0;
return F[n] * 1ll * Finv[n - m] % MOD * Finv[m] % MOD;
}
ll mp[100005];
void init(){
mp[0]=1;
for (int i=1;i<=100000;i++){
mp[i]=mp[i-1]*(2*i-1)%MOD*(2*i)%MOD;
}
}
ll work(int i, int j){
ll ans=mp[i];
cout<<mp[i]<<endl;
for (int k=1;k<=j;k++){
ans=((ans+(k%2==1?-1:1)*p[k]%MOD*comb(j,k)%MOD*F[2*i-k])%MOD+MOD)%MOD;
}
return ans;
}
int main(){
inn();
init();
ofstream fout;
ifstream fin;
fin.open("c.in");
fout.open("c.out");
int T;
fin>>T;
int n,m;
for (int ca=1;ca<=T;ca++){
fin>>n>>m;
fout<<"Case #"<<ca<<": "<<work(n,m)<<endl;
}
return 0;
}