Codeforces Round #107 (Div. 2)

比赛地址:http://codeforces.com/contest/151

A:简单题。

B:模拟题。

C:看p分解成素数的个数

假设p分解为 p=p1^a1*p2^a2*p3^a3****pn^an.

令 sum=a1+a2+a3..+an.

 (1)sum>=3  1赢,任意输出两个素因子的乘积。

 (2)sum==2    2赢,

 (3)sum==1    1赢,输出0

 

D:dfs.把必须相同的两个数的位置连接起来,然后dfs一遍就行了,找出共有num个不同的位置,结果就是 m^num ,注意ans要用64位。

 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cmath>
#include <vector>
using namespace std;

const int maxn = 2005;
const int MOD = 1000000007;
int n,m,k;
vector<int>v[maxn];
int vis[maxn];

void dfs(int t)
{
   vis[t]=1;
   for(int i=0;i<v[t].size();i++)
   {
	   if(vis[v[t][i]]==1)
		   continue;
	   dfs(v[t][i]);
   }
   return ;
}

int main()
{
    while(scanf("%d %d %d",&n,&m,&k)!=EOF)
	{
        for(int i=0;i<n;i++)
		{
			v[i].clear();
			vis[i]=0;
		}

		for(int i=0;i<n-k+1;i++)
           for(int j=i,t=i+k-1;j<i+k;j++,t--)
               v[j].push_back(t);

		int num=0;
        for(int i=0;i<n;i++)
		{
           if(vis[i]==1)
			   continue;
		   num+=1;
		   dfs(i);
		}
		
		__int64 ans=1;
		for(int i=1;i<=num;i++)
			ans=ans*m%MOD;
		printf("%I64d\n",ans);
	}
	return 0;
}


E:Smart  Cheater   节点值出现负值的线段树,

我们可以先求出每两个车站之间的期望利润为 (x[i+1]-x[i])/2-pi*c;m个人是独立的,可以转化为求一段

区间的最大连续和,节点值可能为负值,有m个询问。注意这里的树节点的值可能出现负值,所以我们

在查询函数Find_max()返回一个节点,这个节点值ans记录这个区间[l,r]的最大值,最大坐连续值,最

大右连续值,而且这些最大值都是在区间[l,r]取得的。保证了不超出范围。

具体见SegTree Find_max(int t,int l,int r)函数。

 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cmath>
#include <vector>
using namespace std;

const int maxn = 150005;
const double inf = 1e30;
int n,m,c;
int x[maxn];
int p[maxn];
double s[maxn];
double sum[maxn];

struct SegTree
{
	int l;
	int r;
	double max_l;
	double max_r;
	double max_s;
	double sum;
}T[maxn*4+1];


void Build(int t,int l,int r)
{
	T[t].l=l;
	T[t].r=r;
	T[t].max_l=-inf;
	T[t].max_r=-inf;
	T[t].max_s=-inf;
	T[t].sum=0;
	if(T[t].l<T[t].r-1)
	{
		int mid=(T[t].l+T[t].r)/2;
		Build(2*t,T[t].l,mid);
		Build(2*t+1,mid,T[t].r);
	}
    return ;
}

void Adjust(int t,int l,int r)
{
   if(T[t].l==T[t].r-1)
   {
	   T[t].max_l=s[T[t].l];
	   T[t].max_r=s[T[t].l];
       T[t].max_s=s[T[t].l];
	   T[t].sum=s[T[t].l];
	   return ;
   }
   int mid=(l+r)/2;
   Adjust(2*t,l,mid);
   Adjust(2*t+1,mid,r);
   T[t].sum=T[2*t].sum+T[2*t+1].sum;
   T[t].max_l=max(T[2*t].max_l,T[2*t].sum+T[2*t+1].max_l);
   T[t].max_r=max(T[2*t+1].max_r,T[2*t+1].sum+T[2*t].max_r);
   T[t].max_s=max(max(T[t].max_l,T[t].max_r),max(T[2*t].max_s,T[2*t+1].max_s));
   T[t].max_s=max(T[t].max_s,T[2*t].max_r+T[2*t+1].max_l);
   return ;
}

SegTree Find_max(int t,int l,int r)
{
   if(T[t].l==l && T[t].r==r)
	   return T[t];
   int mid=(T[t].l+T[t].r)/2;
   if(r<=mid)
	   return Find_max(2*t,l,r);
   else if(l>=mid)
	   return Find_max(2*t+1,l,r);
   else
   {
       SegTree ans1=Find_max(2*t,l,mid);
	   SegTree ans2=Find_max(2*t+1,mid,r);
	   SegTree ans;
	   ans.max_l=max(ans1.max_l,sum[mid-1]-sum[l-1]+ans2.max_l);
	   ans.max_r=max(ans2.max_r,sum[r-1]-sum[mid-1]+ans1.max_r);
	   ans.max_s=max(max(ans.max_l,ans.max_r),max(ans1.max_s,ans2.max_s));
	   ans.max_s=max(ans.max_s,ans1.max_r+ans2.max_l);
	   return ans;
   }
}

int main()
{
	int a,b;
    while(scanf("%d %d %d",&n,&m,&c)!=EOF)
	{
       for(int i=1;i<=n;i++)
		   scanf("%d",&x[i]);
	   for(int i=1;i<=n-1;i++)
		   scanf("%d",&p[i]);

	   Build(1,1,n);
	   sum[0]=0.0;
       for(int i=2;i<=n;i++)
	   {
          s[i-1]=(x[i]-x[i-1])/2.0-p[i-1]/100.0*c;
		  sum[i-1]=sum[i-2]+s[i-1];
	   }
	   Adjust(1,1,n);
	   double ans=0;
	   for(int i=1;i<=m;i++)
	   {
		   scanf("%d %d",&a,&b);
		   SegTree temp=Find_max(1,a,b);
		   if(temp.max_s>0)
			   ans+=temp.max_s;
	   }
       printf("%.6f\n",ans);
	}
	return 0;
}


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值