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