A. Crazy Town
題目鏈接
http://codeforces.com/contest/498/problem/A
題目大意
給你一個無限大的區域,這個區域被
思路
很容易想到,最少的穿越次數,就是與線段
但是問題是怎麼找這些直線。我剛開始非常naive地去求每條直線和直線
證明也很容易。假設這條直線和線段
紅名爺就是巨啊!
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#define MAXN 10000
#define EPS 1e-7
using namespace std;
typedef long long int LL;
LL a[MAXN],b[MAXN],c[MAXN];
int n;
int dcmp(LL x)
{
if(x>0) return 1;
if(x<0) return -1;
return 0;
}
int main()
{
LL x1,y1,x2,y2;
scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%I64d%I64d%I64d",&a[i],&b[i],&c[i]);
int tot=0;
for(int i=1;i<=n;i++)
if(dcmp(a[i]*x1+b[i]*y1+c[i])!=dcmp(a[i]*x2+b[i]*y2+c[i]))
tot++;
printf("%d\n",tot);
return 0;
}
B. Name That Tune
題目鏈接
http://codeforces.com/contest/498/problem/B
題目大意
在《開門大吉》節目裏(大霧),主持人給了你
思路
可以想到用DP解決此題。用
即
我們可以優化這個DP,由於
那麼
這只是特殊情況,由於
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#define MAXN 11000
using namespace std;
double f[2][MAXN],ans=0;
int n,t;
int now=1,pre=0;
int main()
{
scanf("%d%d",&n,&t);
f[pre][0]=1;
for(int i=1;i<=n;i++)
{
memset(f[now],0,sizeof(f[now]));
double Pi;
int Ti;
scanf("%lf%d",&Pi,&Ti);
Pi/=100;
double tmp=0;
for(int j=i;j<=t;j++)
{
tmp*=(1-Pi);
tmp+=f[pre][j-1];
if(j-Ti-1>=0) tmp-=f[pre][j-Ti-1]*pow(1-Pi,Ti);
f[now][j]+=tmp*Pi;
if(j-Ti>=0) f[now][j]+=f[pre][j-Ti]*pow(1-Pi,Ti);
ans+=f[now][j];
}
swap(now,pre);
}
printf("%.6f\n",ans);
return 0;
}
C. Array and Operations
題目鏈接
http://codeforces.com/contest/498/problem/C
題目大意
給你
思路
顯然,爲了讓步數最大化,我們每次除以的公約數都是質數。而且對於不同的除數操作,它們之間互不干擾,相同的除數操作會互相干擾。
我們可以先預處理篩素數,然後枚舉
然後每個
代碼
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXV 1000
#define MAXE 21000
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<int,int> pr;
int S,T;
int n,m;
int a[MAXV];
pr opt[MAXV];
struct edge
{
int u,v,cap,next;
}edges[MAXE*2];
int head[MAXV],nCount=0;
void AddEdge(int U,int V,int C)
{
edges[++nCount].u=U;
edges[nCount].v=V;
edges[nCount].cap=C;
edges[nCount].next=head[U];
head[U]=nCount;
}
void add(int U,int V,int C)
{
AddEdge(U,V,C);
AddEdge(V,U,0);
}
int q[MAXE*2];
int layer[MAXV];
bool inX[MAXV],inY[MAXV];
bool CountLayer()
{
memset(layer,-1,sizeof(layer));
int h=0,t=1;
q[h]=S;
layer[S]=1;
while(h<t)
{
int u=q[h++];
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(layer[v]==-1&&edges[p].cap)
{
layer[v]=layer[u]+1;
q[t++]=v;
}
}
}
return layer[T]!=-1;
}
int DFS(int u,int flow)
{
int used=0;
if(u==T) return flow;
for(int p=head[u];p!=-1;p=edges[p].next)
{
int v=edges[p].v;
if(layer[v]==layer[u]+1&&edges[p].cap)
{
int tmp=DFS(v,min(flow-used,edges[p].cap));
edges[p].cap-=tmp;
edges[p^1].cap+=tmp;
used+=tmp;
if(used==flow) break;
}
}
if(!used) layer[u]=-1;
return used;
}
int Dinic()
{
int maxflow=0;
while(CountLayer())
maxflow+=DFS(S,INF);
return maxflow;
}
bool isPrime[31623];
int primes[100000],tot=0;
void getPrime()
{
memset(isPrime,true,sizeof(isPrime));
isPrime[0]=isPrime[1]=false;
for(int i=2;i<31623;i++)
{
if(!isPrime[i]) continue;
primes[++tot]=i;
for(int j=i+i;j<31623;j+=i)
isPrime[j]=false;
}
}
int cnt[MAXV]; //cnt[i]=a[i]可以除prime的次數
int solve(int prime)
{
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
while(a[i]%prime==0)
{
a[i]/=prime;
cnt[i]++;
}
nCount=1;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
{
if(inX[i])
add(S,i,cnt[i]);
else
add(i,T,cnt[i]);
}
for(int i=1;i<=m;i++)
add(opt[i].first,opt[i].second,min(cnt[opt[i].first],cnt[opt[i].second]));
return Dinic();
}
int main()
{
int ans=0;
getPrime();
memset(head,-1,sizeof(head));
S=MAXV-2,T=MAXV-1;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(i&1) inX[i]=true;
else inY[i]=true;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&opt[i].first,&opt[i].second);
if(inX[opt[i].second])
swap(opt[i].first,opt[i].second);
}
for(int i=1;i<=tot;i++)
ans+=solve(primes[i]);
memset(head,-1,sizeof(head));
nCount=1;
for(int i=1;i<=n;i++)
{
if(inX[i])
add(S,i,1);
else
add(i,T,1);
}
for(int i=1;i<=m;i++)
if(a[opt[i].first]==a[opt[i].second]&&a[opt[i].first]>1)
add(opt[i].first,opt[i].second,1);
ans+=Dinic();
printf("%d\n",ans);
return 0;
}