http://codeforces.com/gym/101462
因为某些原因,这场比赛只进行了4小时,我队只过了6题:A,B,E,F,H,I
A题水题,最长上升子序列
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n;
int a[100005];
int b[100005];
int search(int num,int low,int high)
{
int mid;
while (low<=high)
{
mid=(low+high)/2;
if (num>b[mid]) low=mid+1;
else high=mid-1;
}
return low;
}
int dp(int n)
{
int len,pos;
b[1]=a[1];
len=1;
for (int i=2;i<=n;i++)
{
if (a[i]>b[len])
{
len=len+1;
b[len]=a[i];
}
else
{
pos=search(a[i],1,len);
b[pos]=a[i];
}
}
return len;
}
int main()
{
freopen("A.IN","r",stdin);
while (~scanf("%d",&n))
{
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
printf("%d\n",dp(n));
}
return 0;
}
B题是预处理+莫比乌斯反演,莫比乌斯反演用nlogn的容斥原理替换也可以,一开始想到先用每个数去判,看有多少个数是这个数的倍数,然后容斥原理,容斥用莫比乌斯反演去做可以更快,O(n^2),但是感觉这样还是会超时,后来发现可以预处理,即对于一个数可以先求出这个数的所有因子,sqrt(n)求即可。所以时间复杂度为O(n^(3/2))
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 10000
int pri[maxn+5];
int mu[maxn+5];
int p[10005];
int n;
void getMu()
{
mu[1]=1;
for (int i=2;i<=maxn;i++)
{
if (pri[i]==0)
{
pri[++pri[0]]=i;
mu[i]=-1;
}
for (int j=1;j<=pri[0] && pri[j]<=maxn/i;j++)
{
pri[pri[j]*i]=1;
if (i%pri[j]) mu[i*pri[j]]-=mu[i];
else
{
mu[i*pri[j]]=0;
break;
}
}
}
}
int main()
{
freopen("B.IN","r",stdin);
getMu();
while (~scanf("%d",&n))
{
memset(p,0,sizeof(p));
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
for (int j=1;j*j<=x;j++)
{
if (x%j==0)
{
if (j*j==x) p[j]++;
else
{
p[j]++;
p[x/j]++;
}
}
}
}
ll ans=0;
for (int i=1;i<=maxn;i++)
{
ans+=(ll)mu[i]*p[i]*(p[i]-1)*(p[i]-2)*(p[i]-3)/24;
}
printf("%I64d\n",ans);
}
return 0;
}
C题:是一道很裸的2-SAT的模板题
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2005;
const int maxm=2000010;
struct Edge
{
int to,next;
}edge[maxm];
int head[maxn],tot;
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
bool vis[maxn];
int s[maxn],top;
bool dfs(int u)
{
if (vis[u^1]) return false;
if (vis[u]) return true;
vis[u]=true;
s[top++]=u;
for (int i=head[u];i!=-1;i=edge[i].next)
if (!dfs(edge[i].to))
return false;
return true;
}
bool Twosat(int n)
{
memset(vis,false,sizeof(vis));
for (int i=0;i<n;i+=2)
{
if (vis[i] || vis[i^1]) continue;
top=0;
if (!dfs(i))
{
while (top) vis[s[--top]]=false;
if (!dfs(i^1)) return false;
}
}
return true;
}
int n,m;
int main()
{
freopen("C.IN","r",stdin);
while (~scanf("%d%d",&n,&m))
{
init();
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if (x>0) x=(x<<1)-2;
else x=((-x)<<1)-1;
if (y>0) y=(y<<1)-2;
else y=((-y)<<1)-1;
addedge(x,y^1);
addedge(y,x^1);
}
if (Twosat(2*n)) printf("1\n");
else printf("0\n");
}
return 0;
}
E题水题,凸多边形求面积,直接抄模板即可
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const double eps=1e-8;
struct point
{
double x,y;
point(){}
point (double _x,double _y)
{
x=_x;
y=_y;
}
double operator ^(const point &b) const
{
return x*b.y-y*b.x;
}
}p[1000005];
int n;
double CalcArea(point p[],int n)
{
double res=0;
for (int i=0;i<n;i++)
{
res+=(p[i]^p[(i+1)%n])/2;
}
return fabs(res);
}
int main()
{
freopen("E.IN","r",stdin);
while (~scanf("%d",&n) && n!=0)
{
for (int i=0;i<n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
double area;
if (n<3) area=0;
else area=CalcArea(p,n);
printf("%.0f\n",area);
}
return 0;
}
F题并查集,一开始不会把一个元素独立出来,没办法,写了一个O(n)的居然过了
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n;
int f[10005];
int p[10005];
void init()
{
for (int i=1;i<=n;i++)
{
f[i]=i;
}
}
int find_father(int x)
{
if (f[x]==x) return x;
else return f[x]=find_father(f[x]);
}
void Union(int x,int y)
{
f[find_father(y)]=find_father(x);
}
void erase(int x)
{
if (f[x]==x)
{
int flag=-1;
for (int i=1;i<=n;i++)
{
if (f[i]==x)
{
p[i]=1;
flag=i;
}
else p[i]=0;
}
if (flag!=-1)
{
for (int i=1;i<=n;i++)
{
if (p[i]==1) f[i]=flag;
}
}
f[x]=x;
}
else
{
int y=find_father(x);
for (int i=1;i<=n;i++)
{
if (f[i]==x) f[i]=y;
}
f[x]=x;
}
}
int main()
{
freopen("F.IN","r",stdin);
while (~scanf("%d",&n))
{
int n1=0,n2=0;
init();
while (1)
{
char s[10];
scanf("%s",s);
if (s[0]=='c')
{
int x,y;
scanf("%d%d",&x,&y);
if (find_father(x)!=find_father(y)) Union(x,y);
}
else if (s[0]=='q')
{
int x,y;
scanf("%d%d",&x,&y);
if (find_father(x)==find_father(y)) n1++;
else n2++;
}
else if (s[0]=='d')
{
int x;
scanf("%d",&x);
erase(x);
}
else if (s[0]=='e')
{
break;
}
}
printf("%d , %d\n",n1,n2);
}
return 0;
}
H题队友写的
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int eular(int n)
{
int ans=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans-=ans/i;
while(n%i==0)
n/=i;
}
}
if(n>1)ans-=ans/n;
return ans;
}
int main()
{
int T,x;
freopen("H.IN","r",stdin);
while(scanf("%d",&T)!=EOF)
{
long long a=1;
while(T--)
{
scanf("%d",&x);
a=a*(long long)eular(x);
a=a%1000000007;
}
printf("%lld\n",a);
}
return 0;
}
I题队友过的
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n,c;
int a[100005];
int b[100005];
int ans = 0;
int main()
{
freopen("I.IN","r",stdin);
while (~scanf("%d%d",&n,&c))
{
if(n == 0 || c == 0) ans = 0;
else {
if(c % (2*n) == 0)
{
ans = c / (2*n);
}
else{
int t1 = c / (2*n);
int t2 = t1 + 1;
if(t2*(c-t2*n) > t1*(c-t1*n))
{
ans = t2;
}
else ans = t1;
}
}
printf("%d\n",ans);
}
return 0;
}