ACdream原創羣賽(13)のwuyiqi退役專場

這次比賽有好幾個題目都不會做,好好學習吧!雖然有很多想法,但是自己一一否定了  0.0


C、 True Love

看懂題目意思就是一個多重揹包,題目只要求染色方案數,使用 bool型多重揹包可以方便解決這個問題。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;

int a[200],b[200];
int dp[100100],cnt[100100];
int main(){
	int cases,n,m;
	scanf("%d",&cases);
	for (int cas=1;cas<=cases;cas++){
		scanf("%d%d",&n,&m);
		for (int i=1;i<=n;i++) scanf("%d",&a[i]);
		for (int i=1;i<=n;i++) scanf("%d",&b[i]);
		memset(dp,false,sizeof(dp));
		int ans=0;dp[0]=true;
		for (int i=1;i<=n;i++){
			memset(cnt,0,sizeof(cnt));
			for (int j=a[i];j<=m;j++){
				if (dp[j-a[i]]&&!dp[j]&&cnt[j-a[i]]<b[i]){
					ans++;
					dp[j]=true;
					cnt[j]=cnt[j-a[i]]+1;
				}
			}
		}
		printf("Case %d: %d\n",cas,ans);
	}
	return 0;
}


D、 LSS

題目求 連續的最多的相同的字母 的個數。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

char st[200];
int main(){
	int cases;
	scanf("%d",&cases);gets(st);
	while (cases--){
		gets(st);
		int len=strlen(st);
		int sum=1,ans=1;
		for (int i=1;i<len;i++){
			if (st[i-1]==st[i]) sum++;
			else sum=1;
			if (ans<sum) ans=sum;
		}
		printf("%d\n",ans);
	}
	return 0;
}

H、 Salmon and Cat

(a+2)(b+2)=c+2 、 把a+2 、b+2、c+2 看成一個整體,於是題目就變成 求n+2是否被3和5除盡。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

int main(){
	int n;
	while (~scanf("%d",&n)){
		n+=2;
		while (n%3==0) n/=3;
		while (n%5==0) n/=5;
		if (n==1) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}


F、The Arrow

題目大意:

  擲骰子,1-6、給定一個n。我們把我們k次擲骰子的和記爲sum,當前擲骰子點數爲t。
若 sum+t>n  ,sum 不變,
若sum+t==n  遊戲結束
若sum+t<n  繼續遊戲,sum+=t。
問,期望多少次 能結束遊戲。 

這應該叫 期望dp?

我們設dp[x]表示x還期望走多少步能到達n。顯然 dp[n]=0 、dp[0]就是我們要求解的期望。

方程是 dp[x]=(dp[x+1]+dp[x+2]+...+dp[x+6])/6+1   可以這樣理解,x到x+1 期望走1步,1/6的概率、

和n相鄰的6個點n-1到n-6要注意。以n-2爲例  dp[n-2]=dp[n-1]/6+dp[n]/6+dp[n-2]*4/6+1..爲何要加入dp[n-2]呢?因爲n-2自己可以擲出3-6的話可以得到自己。然後我們解方程就可以得到dp[n-2]...

這便是所謂的期望dp 要倒着來做了吧、在這樣算出來之後,可以考慮正向打表,但是這對於初學者不好理解啊= =、

#include <iostream>
#include <cstring>
#include <cstdio>
#define Maxn 100100
using namespace std;

double dp[Maxn];
int main (){
	int cases,n,cnt;
	scanf("%d",&cases);
	while (cases--){
		scanf("%d",&n);
		dp[n]=0;
		for (int i=n-1;i>=0;i--){
			dp[i]=0;cnt=0;
			for (int j=1;j<=6;j++){
				if (i+j>n) cnt++;
				else dp[i]+=dp[i+j];
			}
			dp[i]=(dp[i]+6)/(6-cnt);
		}
		printf("%.2f\n",dp[0]);
	}
	return 0;
}

G、Number Theory

題目大意:所有的數<=222222、給出一個n,和n個數,問有多少對互質的數、

莫比烏斯反演,我還沒怎麼弄明白,以後再來總結。

#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long
#define Maxn 222222
using namespace std;

bool isPri[Maxn+30];
int mu[Maxn+10],pri[Maxn+10],a[Maxn+10],cnt[Maxn+10],num[Maxn+10];
int pnum;
int mobius(int n){
	memset(isPri,true,sizeof(isPri));
	pnum=0;isPri[1]=false;mu[1]=1;
	for (int i=2;i<=n;i++){
		if (isPri[i]){
			pri[++pnum]=i;
			mu[i]=-1;
		}
		for (int j=1;j<=pnum;j++){
			if (i*pri[j]>n) break;
			isPri[i*pri[j]]=false;
			if (i%pri[j]==0){
				mu[i*pri[j]]==0;
				break;
			}
			mu[i*pri[j]]=-mu[i];
		}
	}
}

LL cal(LL x){
	return x*(x-1)/2;
}

int main(){
	mobius(222222);
	int n;
	while (~scanf("%d",&n)){
		int Max=0;
		for (int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			Max=max(Max,a[i]);
		}
		memset(cnt,0,sizeof(cnt));
		memset(num,0,sizeof(num));
		for (int i=1;i<=n;i++){
			num[a[i]]++;
		}
		for (int i=1;i<=Max;i++){
			for (int j=i;j<=Max;j+=i){
				cnt[i]+=num[j];
			}
		}
		LL ans=0;
		for (int i=1;i<=Max;i++){
			ans+=mu[i]*cal(cnt[i]);
		}
		printf("%lld\n",ans);
	}
	return 0;
}


其他還有很多好題目!以後記得一定要補齊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章