第九届福建省大学生程序设计竞赛 部分题解

A题:FZU 2294

这题是无符号的计算,但是有个坑就是我用printf输出一直wa,用cout输出就AC。

#include
#include
#include
#include
#include
#include
using namespace std;
long long unsigned mod; 
mapm;
void init()
{
	mod=1;
	for(int i=1;i<=47;i++)
	mod*=2;
}
int main()
{
	long long unsigned num1 ;
	string a,b,op;
	init();
	while(cin>>op)
	{
		if(op=="def")
		{
			cin>>a>>num1;
			m[a]=(num1+mod)%mod;
		}
		else if(op=="add")
		{
			cin>>a>>b;
			m[a]=(m[a]+m[b])%mod;
		}
		else if(op=="sub")
		{
			cin>>a>>b;
			m[a]=(m[a]-m[b])%mod;
		}
		else if(op=="mul")
		{
			cin>>a>>b;
			m[a]=(m[a]*m[b])%mod;
		}
		else if(op=="div")
		{
			cin>>a>>b;
			m[a]=m[a]/m[b];
		}
		else
		{
			cin>>a>>b;
			m[a]=m[a]%m[b];
		}
		cout<

D题:FZU 2297

这题如果把M改成质数,就是个水题n了,可惜不是,就成了一个好题,为了不丢失精度,每次D操作都得把之前所有的有效M次操作的数相乘,这样才能避免除法,这样时间复杂度是n^2,不过区间问题可用线段树优化成nlogn。单点更新,求最大的区间之积。

#include
#include
#include
using namespace std;
const int maxn=1e5;
long long mod,y,value;
long long tree[4*maxn];
void update(int L,int R,int o,int k)
{
	if(L==R)
	{
		tree[o]=value;
		return;
	}
	int m=(L+R)/2;
	if(k<=m)
	update(L,m,o*2,k);
	else
	update(m+1,R,o*2+1,k);
	tree[o]=tree[o*2]*tree[o*2+1]%mod;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int q,i;
		char op[2];
		scanf("%d%lld",&q,&mod);
		for(i=1;i

H题:FZU 2301

题意:我有n次攻击次数,敌人有m滴血,一次攻击扣一滴血,但是我有1/2的概率攻击的不是这个敌人,求我把他杀死的概率,举个例子,n=2,m=1,假设1为攻击到敌人,0每攻击到敌人,那么有效攻击种类为10,01,11,总攻击种类有四种,那么杀死的概率就是3/4(除法用逆元)

思路:很明显我至少有m次攻击到敌人才能杀死他,那么有效攻击种类为C(m,n)+C(m+1,n)+..+C(n,n),总攻击种类有2^n,由于n最大取1000,可以提前把2^1到2^1000次方的逆元打表,也要先把∑C(i,n)(i=m,m+1,..n)的杨辉三角后缀和打表。

#include
#include
using namespace std;
const int mod=1e9+7;
const int maxn=1e3+10;
long long a[maxn],b[maxn][maxn];
long long pows(long long x,int y)
{
	long long res=1;
	while(y)
	{
		if(y%2==1)
		res=res*x%mod;
		x=x*x%mod;
		y/=2;
	}
	return res;
}
void init()
{
	long long t=2;
	for(int i=1;i=0;j--)
		{
			b[i][j]=(b[i][j]+b[i][j+1])%mod;	
		}	
	}


}
int main()
{
	int T;
	init();
	scanf("%d",&T);
	while(T--)
	{
		int n,m;
		scanf("%d%d",&n,&m);
		if(m==0)
		{
			printf("1\n");	
		}
		else if(n

I题用区间DP记忆化搜索,算了算复杂度为200^3竟然超时了。。。

思路:设d[ i ][ j ][ p ]为区间 i 到 j 的序列,再划分p块的最小值,那么

d[ i ][ j ][ p ]=min(sum(i, k)+dfs(k+1, j ,p-1 )),虽然超时, 但是还是奉献出代码

#include
#include
#include
using namespace std;
const int inf=99999999;
int d[201][201][201],a[201],sum[201];
int n,k;
int pow(int t)
{
	return t*t;
}
void init()
{
	sum[0]=0;
	memset(d,0,sizeof(d));
}
int dfs(int i,int j,int remain)
{
	if(j-i+1

J题:FZU 2303

思路:求一个数学期望,这题就是个推公式题。

第九届福建省大学生程序设计竞赛 部分题解_第1张图片

#include
const int mod=1e9+7;
const int maxn=1e6+20;
long long a[maxn];
long long pows(long long x,int y)
{
	long long res=1;
	while(y)
	{
		if(y&1)
		res=res*x%mod;
		x=x*x%mod;
		y=(y>>1); 
	}
	return res;
}
void init()
{
	int i;
	for(i=1;i

 

 

 

你可能感兴趣的:(比赛----其他比赛题解)