1. 程式人生 > >Wannafly挑戰賽24-A,B,C

Wannafly挑戰賽24-A,B,C

思路:對於大於1的奇數分析,對於3 可以分為1,2,然後2與其他偶數合併,總共2次;考慮最後的偶數也與其他偶數合併,那麼對於5可以分成 1,4 (2次)和 3,2 (4次),7和分為 1,6(2次),3,4(4次)和 5,2(6次)可以發現大於1的奇數的操作次數都是偶數次,那麼說明奇數對於結果是沒有影響的,只要對偶數個數考慮,當偶數個數為偶數是為Bob贏,為奇數則為 Alice贏,對於特殊情況,只有一個奇數時同樣成立,而全為 1時則是 Bob贏

Code :

#include<iostream>
using namespace std;

int main()
{
	int n,s2=0,x,p=0;
	cin>>n;
	for(int i=0;i<n;++i)
	{
		cin>>x;
		if(x%2==0)	++s2;
		if(x>1)	p=1;
	}
	string str="Alice";
	if(!p||s2%2)	str="Bob";
	cout<<str<<endl;
	
	return 0;
}

Code :

#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;

const int MAX_S=10000005;
int p;
int d[MAX_S];

int main()
{
	int a,b;
	while(cin>>p){
		memset(d,0,sizeof(d));
		int s=3;
		for(int i=1;i<=p;s=s*3%p,++i)
			if(!d[s])	d[s]=i;
			else	break;
		LL n=p-2,inv=1,ai=2;
		while(n){
			if(n&1)	inv=inv*ai%p;
			ai=ai*ai%p;
			n>>=1;
		}
		s=inv;
		int sum=p+1;
		for(int i=1;i<=p&&i<sum;s=s*inv%p,++i)
			if(d[s]&&sum>i+d[s]){
				a=i;	b=d[s];
				sum=a+b;
			}
		cout<<a<<" "<<b<<endl;
	}
	
	return 0;
}

易知在放置時操作多次其實和操作一次最終的效果是一樣的
dp[i][j] : 在第 i 個物品天平兩邊相差為 j 的最大收益,
dp[i][j] = max(dp[i][j], dp[i-1][j]);     //不選的情況
dp[i][j+x] = max(dp[i][j+x], dp[i-1][j]+x);  //同側
dp[i][abs(j-x)] = max(dp[i][abs(j-x)], dp[i-1][j]+x);  //異側

Code :

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

const int MAX_N=105;
const int MAX_S=100005;
int n,m;
int dp[MAX_N][MAX_S];

int main()
{
	memset(dp, -1, sizeof(dp));
	dp[0][0]=0;
	scanf("%d%d",&n,&m);
	for(int i=1,x;i<=n;++i)
	{
		scanf("%d",&x);
		for(int j=0;j<MAX_S;++j)
		{
			dp[i][j]=max(dp[i][j],dp[i-1][j]);
			if(j+x<MAX_S&&dp[i-1][j]!=-1){
				dp[i][j+x]=max(dp[i][j+x],dp[i-1][j]+x);
			}
			if(dp[i-1][j]!=-1)
				dp[i][abs(j-x)]=max(dp[i][abs(j-x)],dp[i-1][j]+x);
		}
	}
	int ans=0;
	for(int i=0;i<=m;++i)
		ans=max(ans,dp[n][i]);
	printf("%d",ans);
	
	return 0;
}