Google Kickstart round H 2018

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oidoidoid/article/details/84206530

网址

第一次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

尺取暴力

任意连续的长度为\left \lceil \frac{n}{2} \right \rceil的墙都可以取到,直接求最优解即可

#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了

还是姿势水平不够吧,早早想一想就可以知道暴力的时间复杂度是O\left ( T*m \right )

#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;
	
}

猜你喜欢

转载自blog.csdn.net/oidoidoid/article/details/84206530