T1:博主只拿了60pts exgcd,弱啊
正解其实就是a*b-a-b
这种题考场上一看数据范围应该打表测试一下,发现大概的规律再去证明
结论:对于正整数a,b满足gcd(a,b)=1,我们有ax+by=n无非负整数解的最大正整数n为ab-a-b
证明如下:
我们可以用反证法,假设存在 ax+by=ab−a−b
则
#include
using namespace std;
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%lld",(long long)a*b-a-b);
}
T2:这种大模拟没有写对我也是挺服气自己了。。
思路没理清啊,栈空时才要更新最大值,我在里面就给更新最大值了,ta当然不对啊
son[i]表示i这一层包含的最大值
own[i]表示i这一层自己的值,要是根本进不去的话设成一个最大的负数吧
这样当栈空的时候取一个最大值看看等不等于一开始的
#include
#include
#include
#define INF 1e9
using namespace std;
int ha[1005],stack[1200],num,own[1200],son[1200];
char st[1200];
int js(char st[])
{
int i=0,b=0;
while (st[i]>='0' && st[i]<='9') b=b*10+st[i]-'0',i++;
return b;
}
int main()
{
freopen("complexity.in","r",stdin);
freopen("complexity.out","w",stdout);
int T;
scanf("%d",&T);
while (T--)
{
int bb=0,b=0,n,i,vv=0;
scanf("%d",&n);
memset(ha,0,sizeof(ha));
memset(son,0,sizeof(son));
memset(own,0,sizeof(own));
num=0;
scanf("%s",st);
int ls=strlen(st);
if (n%2!=0) vv=1;
for (i=0;iif (st[i]=='(')
{
i++;
if (st[i]=='1') break;
else
{
while (st[i]!='^') i++;
i++;
while (st[i]>='0' && st[i]<='9') b=b*10+st[i]-'0',i++;
break;
}
}
for (i=1;i<=n;i++)
{
char ss[205],zm[205],f[205],e[205];
scanf("%s",ss);
if (ss[0]=='F')
{
scanf("%s%s%s",&zm,&f,&e);
if (ha[zm[0]])vv=1;
ha[zm[0]]=1;
if ((f[0]=='n' && e[0]!='n') || (f[0]!='n' && e[0]!='n' && js(f)>js(e))) own[++num]=-INF;
else if ((e[0]>='0' && e[0]<='9') || (f[0]=='n' && e[0]=='n')) own[++num]=0;
else own[++num]=1;
son[num-1]=max(own[num],son[num-1]);
stack[num]=zm[0];
}
else
{
if (!num)vv=1;
ha[stack[num]]=0;
own[num]+=son[num];
son[num-1]=max(own[num],son[num-1]);
son[num]=0; own[num]=0;
num--;
if (!num) bb=max(son[num],bb);
}
}
if (vv || num) {printf("ERR\n");continue;}
if (bb==b) printf("Yes\n");
else printf("No\n");
}
return 0;
}
T3:Day1的dp。。
30pts暴力
T1:各种数据都能过,被NOIP的数据卡了,竟然是因为精度开的太大了。。。1e-18就A了,好气哦
我用的是dij最短路判断 O(n2) 连边求就好了
#include
#include
#include
#include
#define LL long long
using namespace std;
const LL INF=1e18;
const double eps=1e-18;
const int N=1005;
const int M=N*N;
struct hh{int x,y,z;}ball[N];
struct www{int id;LL z;}q[M+N];
int tot,nxt[M],point[N],v[M],num;LL dis[N];
int n,r,h,t;bool vis[N];
bool operator <(const www &a,const www &b){return a.zint x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void push(www now)
{
q[++num]=now;
int x=num,fa=x>>1;
while (fa && q[x]<q[fa])
{
swap(q[x],q[fa]);
x=fa; fa>>=1;
}
}
void pop()
{
q[1]=q[num--];
int now=1,l=now<<1,r=now<<1|1,better=l;
if (r<=num && q[r]<q[l]) better=r;
while (better<=num && q[better]<q[now])
{
swap(q[better],q[now]);
now=better,l=now<<1,r=now<<1|1,better=l;
if (r<=num && q[r]<q[l]) better=r;
}
}
void dij()
{
memset(dis,0x7f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[0]=0;
push((www){0,0});
while (num)
{
www now=q[1]; pop();
if (vis[now.id]) continue;
vis[now.id]=1;
for (int i=point[now.id];i;i=nxt[i])
if (dis[v[i]]>dis[now.id]+1)
{
dis[v[i]]=dis[now.id]+1;
push((www){v[i],dis[v[i]]});
}
}
}
bool jiao(int i,int j)
{
double dd=(double)sqrt((LL)(ball[i].x-ball[j].x)*(ball[i].x-ball[j].x)+(LL)(ball[i].y-ball[j].y)*(ball[i].y-ball[j].y)+(LL)(ball[i].z-ball[j].z)*(ball[i].z-ball[j].z));
if (dd<=(double)2*r || abs(dd-2*r)<=eps) return 1;
return 0;
}
int main()
{
freopen("cheese.in","r",stdin);
freopen("cheese.out","w",stdout);
int T,i,j,nn;scanf("%d",&T);
while (T--)
{
tot=0; memset(point,0,sizeof(point));
scanf("%d%d%d",&nn,&h,&r);
t=nn+1;n=0;
for (i=1;i<=nn;i++)
{
++n;
scanf("%d%d%d",&ball[n].x,&ball[n].y,&ball[n].z);
if ((ball[n].z-r>=h) || (ball[n].z+r<=0)) n--;
}
for (i=1;i<=n;i++)
{
if (ball[i].z+r>=h) addline(i,t);
for (j=i+1;j<=n;j++)
if (jiao(i,j)) addline(i,j);
if (ball[i].z-r<=0) addline(0,i);
}
dij();
if (dis[t]>INF) printf("No\n");else printf("Yes\n");
}
}
T2:最弱的博主今年唯一A掉的题目
其实就是一个暴力啊,分了两部分来写来稳住40pts
我们可以用dp[i]表示i这个状态(二进制),其中1表示这个点经过了,0表示没有经过
再用f[i][j]表示i这个状态每个点到达j这个点的距离,然后暴力转移一波就好了
效率是 O(n4∗2n) 看着很大对吧,可是这是极限效率,这个效率是今年跑的最快的做法辣
#include
#include
#include
#include
#define LL long long
using namespace std;
const int N=2200;
const LL INF=1e18;
int tot,nxt[N],point[N],v[N],c[N],f[5000][15],h[N];
LL dp[5000];bool vis[N];
void addline(int x,int y,int z)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; c[tot]=z;
}
void spfa(int x)
{
queue<int>q;
q.push(x);
while (!q.empty())
{
int now=q.front(); q.pop();
vis[now]=0;
for (int i=point[now];i;i=nxt[i])
if (h[v[i]]>h[now]+1)
{
h[v[i]]=h[now]+1;
if (!vis[v[i]]) vis[v[i]]=1,q.push(v[i]);
}
}
}
int main()
{
int n,m,i,j,k,ii,num,lz=0,l;LL ans=INF;bool vv=1;
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addline(x,y,z);if (lz!=z && i!=1) vv=0;
lz=z;
}
if (vv)
{
for (i=1;i<=n;i++)
{
memset(h,0x7f,sizeof(h));
memset(vis,0,sizeof(vis));h[i]=0;
spfa(i);LL qz=0;
for (j=1;j<=n;j++) qz+=h[j]*lz;
ans=min(ans,qz);
}
}
else
{
num=(1<1;
for (i=1;i<=n;i++)
{
memset(dp,0x7f,sizeof(dp));
dp[1<1]=0;f[1<1][i]=0;
for (j=0;j<=num;j++)
if (dp[j]for (k=1;k<=n;k++)
if ((j>>k-1)&1)
{
for (ii=point[k];ii;ii=nxt[ii])
if (!((j>>(v[ii]-1)&1)))
{
if (dp[j|(1<<(v[ii]-1))]>dp[j]+(LL)(f[j][k]+1)*c[ii])
{
dp[j|(1<<(v[ii]-1))]=dp[j]+(LL)(f[j][k]+1)*c[ii];
for (l=1;l<=n;l++) f[j|(1<<(v[ii]-1))][l]=f[j][l];
f[j|(1<<(v[ii]-1))][v[ii]]=f[j][k]+1;
}
}
}
}
ans=min(ans,dp[num]);
}
}
printf("%lld",ans);
}
T3:waiting