Comet OJ - Contest #0
A:化成x-√n=y+z-√4yz的形式,则显然n是完全平方数时有无数组解,否则要求n=4yz,暴力枚举n的因数即可。注意判断根号下是否不小于0。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define P 1000000007
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
signed main()
{
int T=read();
while (T--)
{
int n=read();
int w=sqrt(n);
if (w*w==n||(w+1)*(w+1)==n||(w-1)*(w-1)==n) cout<<"infty"<<endl;
else
{
if (n%4) cout<<0<<' '<<0<<endl;
else
{
n/=4;
int cnt=0,ans=0;
for (int i=1;i*i<=n;i++)
if (n%i==0)
{
if (i+n/i>w) cnt++,ans=(ans+1ll*n*(i+n/i))%P;
}
cout<<cnt<<' '<<ans<<endl;
}
}
}
return 0;
//NOTICE LONG LONG!!!!!
}
B:f[i][j][k]表示第i步后左边有j个已访问城市右边有k个已访问城市的概率,转移显然。虽然是在一个环上,但不看成环也没有问题,最后对n取min即可。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define P 1000000007
#define N 510
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int T,f[N][N][N];
int ksm(int a,int k)
{
int s=1;
for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
return s;
}
signed main()
{
T=read();
while (T--)
{
int n=read(),m=read(),k=read(),p=read(),q=read();
for (int i=1;i<=m;i++)
for (int j=0;j<i;j++)
for (int k=0;k<i;k++)
f[i][j][k]=0;
f[1][0][0]=1;
for (int i=1;i<m;i++)
for (int x=0;x<i;x++)
for (int y=0;y<i;y++)
f[i+1][max(x-1,0)][y+1]=(f[i+1][max(x-1,0)][y+1]+1ll*p*f[i][x][y])%P,
f[i+1][x+1][max(y-1,0)]=(f[i+1][x+1][max(y-1,0)]+1ll*q*f[i][x][y])%P,
f[i+1][x][y]=(f[i+1][x][y]+1ll*(100-p-q)*f[i][x][y])%P;
int ans=0;
for (int x=0;x<m;x++)
for (int y=0;y<m;y++)
ans=(ans+1ll*f[m][x][y]*ksm(min(x+y+1,n),k))%P;
cout<<ans<<endl;
}
return 0;
//NOTICE LONG LONG!!!!!
}
C:容易发现相当于要求两点间存在至少两条边不重复路径,也即两点在同一边双内,用LCT维护边双即可。具体见https://www.cnblogs.com/Gloid/p/10056499.html。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1000010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
#define lself tree[tree[k].fa].ch[0]
#define rself tree[tree[k].fa].ch[1]
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,q,fa[N],fa2[N],size[N];
ll ans;
struct data{int ch[2],fa,rev;
}tree[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int find2(int x){return fa2[x]==x?x:fa2[x]=find2(fa2[x]);}
void rev(int k){if (k) swap(lson,rson),tree[k].rev^=1;}
void down(int k){if (tree[k].rev) rev(lson),rev(rson),tree[k].rev=0;}
int whichson(int k){return rself==k;}
bool isroot(int k){return lself!=k&&rself!=k;}
void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
void move(int k)
{
int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa;
tree[k].ch[!p]=fa,tree[fa].fa=k;
}
void splay(int k)
{
push(k);
while (!isroot(k))
{
int fa=tree[k].fa;
if (!isroot(fa))
if (whichson(fa)^whichson(k)) move(k);
else move(fa);
move(k);
}
}
void access(int k){for (int t=0;k;t=k,k=tree[k].fa=find(tree[k].fa)) splay(k),tree[k].ch[1]=t;}
void makeroot(int k){access(k),splay(k),rev(k);}
void link(int x,int y){makeroot(x),tree[x].fa=y,fa2[find2(x)]=find2(y);}
ll C(int x,int y){return 1ll*x*(x-1)/2;}
void dfs(int k,int x)
{
if (!k) return;
if (find(k)!=x)
{
ans-=C(size[x],2);ans-=C(size[find(k)],2);
size[x]+=size[find(k)];
ans+=C(size[x],2);
fa[find(k)]=x;
}
dfs(lson,x),dfs(rson,x);
}
void addedge(int x,int y)
{
if (find2(x)!=find2(y)) link(x,y);
else
{
makeroot(x),access(y),splay(y);
dfs(tree[y].ch[0],y);tree[y].ch[0]=0;
}
}
int main()
{
int T=read();
while (T--)
{
n=read(),m=read();
ans=0;ll tot=0;
for (int i=1;i<=n;i++) fa[i]=i,fa2[i]=i,size[i]=1,tree[i].ch[0]=tree[i].ch[1]=tree[i].fa=tree[i].rev=0;
for (int i=1;i<=m;i++)
{
int x=find(read()),y=find(read());
if (x!=y) addedge(x,y);
tot^=i*ans;
}
cout<<tot<<endl;
}
return 0;
}
D:考虑暴力,即枚举每道题的做法,然后给每道题一个贪心顺序,大约是T*86*6!的过不掉。注意到值域很小,考虑以此dp,并把贪心顺序放到外层,即f[S][i][j]表示已做完S集合的题目,第一个人最后做题时刻为i,第二个人最后做题时刻为j时,第三个人最早的最后做题时刻,转移考虑下一步贪心的做哪个题以及怎么做即可,大约是T*26*1802*6*8。虽然复杂度看起来仍然非常爆炸,但容易发现很多状态都是无法到达的,转移时先看一下当前状态dp值是否合法即可,这样内部的6*8几乎可以无视。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int a[10][10],f[1<<6][200][200],size[1<<6];
int main()
{
int T=read();
for (int i=1;i<(1<<6);i++) size[i]=size[i^(i&-i)]+1;
while (T--)
{
for (int i=0;i<6;i++)
cin>>a[i][1]>>a[i][2]>>a[i][4]>>a[i][3]>>a[i][5]>>a[i][6]>>a[i][7];
memset(f,42,sizeof(f));f[0][0][0]=0;
int ans=0,ans2=0;
for (int i=0;i<(1<<6);i++)
{
for (int j=0;j<=180;j++)
for (int k=0;k<=180;k++)
if (f[i][j][k]<=180)
{
for (int x=0;x<6;x++) if (!(i&(1<<x)))
{
int u=i|(1<<x);
f[u][min(j+a[x][1],181)][k]=min(f[u][min(j+a[x][1],181)][k],f[i][j][k]);
f[u][j][min(k+a[x][2],181)]=min(f[u][j][min(k+a[x][2],181)],f[i][j][k]);
f[u][j][k]=min(f[u][j][k],f[i][j][k]+a[x][4]);
int v=min(max(max(j,k),f[i][j][k])+a[x][7],181);
f[u][v][v]=min(f[u][v][v],v);
v=min(max(j,k)+a[x][3],181);
f[u][v][v]=min(f[u][v][v],f[i][j][k]);
v=min(max(j,f[i][j][k])+a[x][5],181);
f[u][v][k]=min(f[u][v][k],v);
v=min(max(k,f[i][j][k])+a[x][6],181);
f[u][j][v]=min(f[u][j][v],v);
}
}
}
for (int i=1;i<(1<<6);i++)
for (int j=0;j<=180;j++)
for (int k=0;k<=180;k++)
if (f[i][j][k]<=180)
{
if (size[i]>ans||size[i]==ans&&max(max(j,f[i][j][k]),k)<ans2)
{
ans=size[i];
ans2=max(max(j,f[i][j][k]),k);
}
}
cout<<ans<<' '<<ans2<<endl;
}
return 0;
}
E:考虑处理出前后缀求LIS用的单调栈。注意到修改一个数后LIS要么不变要么+1,所以维护出有用的前后缀每一对LIS的拼接结果即可。注意还要考虑修改后LIS仍不包含当前数的情况。代码有大量冗余。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
#define ll long long
#define N 100010
#define inf 1000000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,a[N],ans,p[N],q[N],f[N][2],g[N][2],stkx[N],stky[N],cnt;
multiset<int> q1,q2;
int main()
{
int T=read();
while (T--)
{
n=read();
for (int i=1;i<=n;i++) a[i]=read();
q[0]=inf;for (int i=1;i<=n;i++) q[i]=-1;
g[n+1][0]=0,g[n+1][1]=inf;ans=0;
for (int i=n;i>=1;i--)
{
int l=0,r=ans;
while (l<=r)
{
int mid=l+r>>1;
if (q[mid]>a[i]) g[i][0]=mid+1,l=mid+1;
else r=mid-1;
}
stkx[i]=g[i][0],stky[i]=q[g[i][0]];
g[i][1]=q[g[i][0]]=a[i];
ans=max(ans,g[i][0]);
}
cnt=0;q1.clear(),q2.clear();
p[0]=-1;for (int i=1;i<=n;i++) p[i]=inf;
if (q[ans]>p[0]) cnt++;
if (q[ans]>p[0]+1) q1.insert(p[0]);
if (q[ans-1]>p[0]+1) q2.insert(p[0]);
f[0][0]=0,f[0][1]=-1;
int mx=0;
for (int i=1;i<=n;i++)
{
if (q[stkx[i]]>p[ans-stkx[i]]+1) q1.erase(q1.find(p[ans-stkx[i]]));
if (ans>=stkx[i]+1) if (q[stkx[i]]>p[ans-stkx[i]-1]+1) q2.erase(q2.find(p[ans-stkx[i]-1]));
if (q[stkx[i]]>p[ans-stkx[i]]) cnt--;
q[stkx[i]]=stky[i];
if (q[stkx[i]]>p[ans-stkx[i]]+1) q1.insert(p[ans-stkx[i]]);
if (ans>=stkx[i]+1) if (q[stkx[i]]>p[ans-stkx[i]-1]+1) q2.insert(p[ans-stkx[i]-1]);
if (q[stkx[i]]>p[ans-stkx[i]]) cnt++;
if (!q1.empty()) printf("%d %d\n",ans+1,(*q1.begin())+1);
else if (cnt) printf("%d %d\n",ans,0);
else printf("%d %d\n",ans,(*q2.begin())+1);
int l=0,r=mx;
while (l<=r)
{
int mid=l+r>>1;
if (p[mid]<a[i]) f[i][0]=mid+1,l=mid+1;
else r=mid-1;
}
mx=max(mx,f[i][0]);
if (q[ans-f[i][0]]>p[f[i][0]]+1) q1.erase(q1.find(p[f[i][0]]));
if (ans>=f[i][0]+1) if (q[ans-f[i][0]-1]>p[f[i][0]]+1) q2.erase(q2.find(p[f[i][0]]));
if (q[ans-f[i][0]]>p[f[i][0]]) cnt--;
f[i][1]=p[f[i][0]]=a[i];
if (q[ans-f[i][0]]>p[f[i][0]]+1) q1.insert(p[f[i][0]]);
if (ans>=f[i][0]+1) if (q[ans-f[i][0]-1]>p[f[i][0]]+1) q2.insert(p[f[i][0]]);
if (q[ans-f[i][0]]>p[f[i][0]]) cnt++;
}
}
return 0;
}
F:显然求出每个子集的最大面积后就能通过O(3n)的状压dp得到答案。有一个结论是,要使面积最大,多边形顶点一定共圆,证明没怎么懂。于是找出圆半径就可以了。容易想到二分,为了确定二分方向,先作一个以最长边为直径的圆,分两种情况考虑:若所有边覆盖的圆心角之和>2π,圆半径增大时覆盖的圆心角会变小;若所有边覆盖的圆心角之和<2π,其中最长边覆盖的应该是优弧,圆半径增大时覆盖的圆心角会变大。以此二分即可。不知道为啥就是过不了,弃了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cassert>
using namespace std;
#define ll long long
#define N 13
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int T,n,a[N],from[1<<N];
long double s[1<<N],f[1<<N];
const long double PI=acos(-1.0);
long double A(long double r,long double a)
{
return 2*asin(a/2/r);
}
long double angle(long double k,int S,int op)
{
long double alpha=0;
int mx=0;for (int i=0;i<n;i++) if (S&(1<<i)) mx=max(mx,a[i]);
for (int i=0;i<n;i++)
if (S&(1<<i))
if (op==1&&a[i]==mx) alpha+=2*PI-A(k,a[i]);
else alpha+=A(k,a[i]);
return alpha;
}
long double calc(long double k,int S,int op)
{
long double area=0;
int mx=0;for (int i=0;i<n;i++) if (S&(1<<i)) mx=max(mx,a[i]);
for (int i=0;i<n;i++)
if (S&(1<<i))
{
if (a[i]==mx&&op==1) area-=a[i]*sqrt(k*k-(a[i]/2.0)*(a[i]/2.0))/2;
else area+=a[i]*sqrt(k*k-(a[i]/2.0)*(a[i]/2.0))/2;
}
return area;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
T=read();
while (T--)
{
n=read();
for (int i=0;i<n;i++) a[i]=read();
for (int i=0;i<(1<<n);i++)
{
s[i]=0;
int S=0,mx=0;
for (int j=0;j<n;j++) if (i&(1<<j)) S+=a[j],mx=max(mx,a[j]);
if (2*mx<S)
{
int op=angle(mx/2.0,i,0)<=2*PI;//op=1时 最长边的角用2π去减 此时角度之和<2π
long double l=mx/2.0,r=1000000,ans=l;
for (int j=1;j<=100;j++)
{
long double mid=(l+r)/2;
if (op==(angle(mid,i,op)<=2*PI)) ans=mid,l=mid;
else r=mid;
}
s[i]=calc(ans,i,op);
}
}
f[0]=1;
double qwq=0;int id=0;
for (int i=1;i<(1<<n);i++)
{
from[i]=0;f[i]=0;
for (int j=i;j;j=j-1&i)
if (s[j]*f[i^j]>f[i]) f[i]=s[j]*f[i^j],from[i]=i^j;
if (f[i]>qwq) qwq=f[i],id=i;
}
printf("%.10lf\n",qwq);
int cnt=0,b[N];
for (int i=id;i;i=from[i])
{
int x=i^from[i],s=0,mx=0;
for (int j=0;j<n;j++) if (x&(1<<j)) s+=a[j],mx=max(mx,a[j]);
if (2*mx<s) b[++cnt]=x;
}
cout<<cnt<<endl;
for (int i=1;i<=cnt;i++)
{
int s=0;
for (int j=0;j<n;j++) if (b[i]&(1<<j)) s++;
cout<<s<<' ';
for (int j=0;j<n;j++) if (b[i]&(1<<j)) cout<<a[j]<<' ';
cout<<endl;
}
}
return 0;
}
没有小裙子呜呜呜
Comet OJ - Contest #0的更多相关文章
- Comet OJ - Contest #0题解
传送门 菜爆了--总共只有一道题会做的--而且也没有短裙好难过 为啥必须得有手机才能注册账号啊喂--歧视么-- \(A\) 解方程 推一下柿子大概就是 \[x-\sqrt{n}=y+z+2\sqrt{ ...
- 【Comet OJ - Contest #0 A】解方程(数学水题)
点此看题面 大致题意: 给定自然数\(n\),让你求出方程\(\sqrt{x-\sqrt n}+\sqrt y-\sqrt z=0\)的自然数解\(x,y,z\)的数量以及所有解\(xyz\)之和. ...
- Comet OJ - Contest #0 A题 解方程 (数学)
题目描述 小象同学在初等教育时期遇到了一个复杂的数学题,题目是这样的: 给定自然数 nn,确定关于 x, y, zx,y,z 的不定方程 \displaystyle \sqrt{x - \sqrt{n ...
- Comet OJ Contest #0 解方程(暴力)
题意: 给定自然数n,求满足$\displaystyle \sqrt{x-\sqrt{n}}=\sqrt{z}-\sqrt{y}$的x,y,z,输出解的个数以及所有解 xyz的和 n<=1e9, ...
- Comet OJ - Contest #2 简要题解
Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...
- Comet OJ - Contest #2简要题解
Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...
- Comet OJ - Contest #4--前缀和
原题:Comet OJ - Contest #4-B https://www.cometoj.com/contest/39/problem/B?problem_id=1577传送门 一开始就想着暴力打 ...
- Comet OJ - Contest #11 题解&赛后总结
Solution of Comet OJ - Contest #11 A.eon -Problem designed by Starria- 在模 10 意义下,答案变为最大数的最低位(即原数数位的最 ...
- Comet OJ - Contest #8
Comet OJ - Contest #8 传送门 A.杀手皇后 签到. Code #include <bits/stdc++.h> using namespace std; typede ...
随机推荐
- HashMap是如何工作的
目录 1 HashMap在JAVA中的怎么工作的? 2 什么是哈希? 3 HashMap 中的 Node 类 4 键值对在 HashMap 中是如何存储的 5 哈希碰撞及其处理 6 HashMap 的 ...
- git学习之时光穿梭机
"x"修改readme.txt文件,改成如下内容: Git is a distributed version control system. Git is free softwar ...
- Item 16: 让const成员函数做到线程安全
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 如果我们在数学领域里工作,我们可能会发现用一个类来表示多项式会很方 ...
- [UWP]为附加属性和依赖属性自定义代码段(兼容UWP和WPF)
1. 前言 之前介绍过依赖属性和附加属性的代码段,这两个代码段我用了很多年,一直都帮了我很多.不过这两个代码段我也多年没修改过,Resharper老是提示我生成的代码可以修改,它这么有诚意,这次就只好 ...
- Python-time模块-58
time 模块: Eva_J import time time.sleep(100) #时间睡眠 print(time.time()) #返回一个以秒为单位的时间 时间模块 和时间有关系的我们就要用到 ...
- H5 62-浮动元素字围现象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【评分】BETA 版冲刺前准备
[评分]BETA 版冲刺前准备 总结 本次作业较为简洁,计1分,按时提交计分,不提交不计分. 详细得分 组 短学号 名 分数 Boy Next Door 114 显东 1 Boy Next Door ...
- 开发工程中遇到的BUG
Xcode7自带Git创建的项目"Couldn’t communicate with a helper application" git xcode7 zhunjiee 2015年 ...
- VMware威睿
VMware总部位于美国加州帕洛阿尔托 [1] ,是全球云基础架构和移动商务解决方案厂商,提供基于VMware的解决方案, 企业通过数据中心改造和公有云整合业务,借助企业安全转型维系客户信任 [2- ...
- 常见的 CSRF、XSS、sql注入、DDOS流量攻击
CSRF攻击 :跨站请求伪造攻击 ,CSRF全名是Cross-site request forgery,是一种对网站的恶意利用,CSRF比XSS更具危险性 攻击者一般会使用吸引人的图片去引导用户点击进 ...