比赛地址: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;
}