B题
模拟(1+/5)/2进制,以前写过。
//{
using namespace std;
//#pragma warning(disable:4996)
//#pragma comment(linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<cmath>
#define ll long long
#define clr(x,y) memset(x,y,sizeof(x))
#define ww while
#define r1(i,a,b) for(int i=a;i< b;i++)
#define r2(i,a,b) for(int i=a;i<=b;i++)
#define r3(i,a,b) for(int i=a;i> b;i--)
#define r4(i,a,b) for(int i=a;i>=b;i--)
#define r5(i,a,n) for(int i=1;i<=n;i++)sf1(a[i])
#define r6(i,a,s,t) for(int i=s;i<=t;i++)pf("%d%c",a[i],i-(t)?' ':'\n')
#define ss(x) sf("%s",x)
#define sf1(x) sf("%d",&x)
#define sf2(x,y) sf("%d%d",&x,&y)
#define sf3(x,y,z) sf("%d%d%d",&x,&y,&z)
#define pd(x,y) printf("%d%c",x,(char)y)
#define sf scanf
#define pf printf
#define pct(x) __builtin_popcount(x)
#define ctz(x) __builtin_ctz(x)
const int inf=0x3f3f3f3f;
const ll MOD=1e9+7;
const int o=200;
struct STC
{
int a[420],l,r;
STC(){clr(a,0);}
void E(){clr(a,0);a[o]=1;l=r=o;}
void out()
{
r4(i,r,o)printf("%d",a[i]);putchar('.');r4(i,o-1,l)printf("%d",a[i]);
}
void get(char c[])
{
int len=strlen(c);
int pos;
r1(i,0,len)if(c[i]=='.')pos=i;
r=pos+199;l=pos+201-len;
r1(i,0,pos)a[r-i]=c[i]-'0';
r1(i,pos+1,len)a[pos+200-i]=c[i]-'0';
}
void add(int p)
{
a[p]++;
ww(a[p]==2)
{
a[p]=0;
a[p-2]++;a[p+1]++;
p-=2;
}
r4(i,400,2)if(a[i]&&a[i-1])a[i]=a[i-1]=0,a[i+1]=1,i=i+3;
l=400,r=-1;
r2(i,2,400)if(a[i]){l=min(l,i),r=max(i,r);}//printf("%d ",i);}
}
};
STC two,th;
STC add(STC x,STC y)
{
r2(i,y.l,y.r)if(y.a[i])x.add(i);
return x;
}
STC s[40];
bool ok[31];
int main()
{
int n;
s[1].get("10.01");
r2(i,2,32)s[i]=add(s[i-1],s[i-1]);
ww(~sf1(n))
{
if(n<=1)pd(n,10);
else
{
clr(ok,0);
r2(i,0,30)if((1<<i)&n)ok[i]=1;
int st;
r2(i,1,30)if(ok[i]){st=i;break;}
STC tm=s[st];
r2(i,st+1,30)if(ok[i]){tm=add(tm,s[i]);}
if(n&1)tm.add(200);
tm.out();puts("");
}
}
}
C题
二分
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
ll n,s,t;
double p;
ll a[2000010],b[2000010];
ll d[50];
ll get(ll val)
{
ll ret=0;
for(ll mask=0;mask<(1<<s);mask++)
{
ret+=upper_bound(b,b+(1<<t),val-a[mask])-b;
}
return ret;
}
int main()
{
int cas;scanf("%d",&cas);
while(cas--)
{
scanf("%lld%lf",&n,&p);
for(ll i=1;i<=n;i++)scanf("%lld",&d[i]);
if(p<=0.0)
{
puts("0");continue;
}
s=n/2,t=n-s;
for(ll mask=0;mask<(1<<s);mask++)
{
ll x=0;
for(ll j=0;j<s;j++)if(mask&(1<<j))x+=d[j+1];
a[mask]=x;
}
sort(a,a+(1<<s));a[1<<s]=1e12;
for(ll mask=0;mask<(1<<t);mask++)
{
ll x=0;
for(ll j=0;j<t;j++)if(mask&(1<<j))x+=d[s+j+1];
b[mask]=x;
}
sort(b,b+(1<<t));b[1<<t]=1e12;
ll l=1,r=40000,mid;
while(l<r)
{
mid=l+r>>1;
if(get(mid)/((double)(1LL<<n))<p)l=mid+1;
else r=mid;
}
ll ans=1e16;
for(ll mask=0;mask<(1<<s);mask++)
{
ll pos=lower_bound(b,b+(1<<t),l-a[mask])-b;
ans=min(ans,b[pos]+a[mask]);
}
printf("%lld\n",ans);
}
}
F题
题目中说n<=100,其实比100大。
高斯消元
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
int n,m,in[300],g[300][300];
vector<int>V[300];
namespace G
{
const int _=300;
double eps=1e-9;
typedef double ml;
ml a[_][_],X[_];
bool Gauss(ml a[][_],int va,ml X[],int equ,int add=0)
//va是未知量的个数,equ是式子个数,add是增广矩阵
{
for(int r=1;r<=equ;r++)
{
int mx=r;
for(int i=r+1;i<=equ;i++)if(fabs(a[mx][r])<fabs(a[i][r]))mx=i;
if(fabs(a[mx][r])<eps)return 0;
if(mx!=r)for(int i=r;i<=va+1+add;i++)swap(a[mx][i], a[r][i]);
for(int i=r+1;i<=va+1+add;i++)a[r][i]/=a[r][r]; a[r][r]=1;//化简
for(int i=1;i<=equ;i++)if(i!=r)
{
for(int j=r+1;j<=va+1+add;j++)a[i][j]-=a[r][j]*a[i][r];
a[i][r]=0;
}
}
return 1;
}
void out(int n,int m)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)printf("%lf ",a[i][j]);puts("");
}
}
int sta[300];
void Go()
{
memset(a,0,sizeof a);
memset(X,0,sizeof X);
for(int i=1;i<n;i++)
{
int len=V[i].size();
for(int j=0;j<len;j++)
{
int v=V[i][j];
a[i][v]=1.0/in[v];
}
a[i][i]=-1;a[i][n+1]=0;
}
for(int i=1;i<=n+1;i++)a[n][i]=1;
int add=0;
for(int k=1;k<n;k++)if(g[n][k]==0)
{
sta[++add]=k;
for(int i=1;i<n;i++)
{
a[i][n+1+add]=g[n][i]?1.0/(in[n]+1):0;
}
a[k][n+1+add]=1.0/(in[n]+1);
a[n][n+1+add]=1.0;
}
if(!Gauss(a,n,X,n,add))
{
puts("INF");return;
}
double now=fabs(a[n][n]);
int ans=-1;
for(int i=n+2;i<=n+1+add;i++)
{
if(now>fabs(a[n][i]))
now=fabs(a[n][i]),ans=sta[i-n-1]-1;
}
printf("%d %d\n",1,ans);
}
}
int main()
{
int cas;scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
memset(g,0,sizeof g);
memset(in,0,sizeof in);
for(int i=1;i<=n;i++)V[i].clear();
while(m--)
{
int x,y;scanf("%d%d",&x,&y);
if(x!=y)g[x+1][y+1]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i!=j&&g[i][j])
{
in[i]++;
V[j].push_back(i);
}
}
G::Go();
}
}
I题
字符串哈希
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
ll mod=1e12+7,t=1331;
ll len,m,l,ans;
char c[100010];
ll sta[100010],top;
map<ll,ll>M;
ll jie[100010];
int main()
{
jie[0]=1;
for(ll i=1;i<=100000;i++)jie[i]=jie[i-1]*t%mod;
while(~scanf("%lld%lld",&m,&l))
{
scanf("%s",c+1);
ans=0;
len=strlen(c+1);
for(ll i=1;i<=l&&i+m*l-1<=len;i++)
{
if(i==1)
{
top=0;
ll tmp=0,num=0;
for(ll j=i;j<=len;j++)
{
++num;
tmp=(tmp+c[j]*jie[l-num])%mod;
if(num==l)
{
sta[++top]=tmp;
tmp=0;num=0;
}
}
}
else
{
top=(len-i+1)/l;
for(ll j=1;j<=top;j++)
{
sta[j]-=c[i-1+l*(j-1)]*jie[l-1]%mod;
sta[j]=(sta[j]%mod+mod)%mod;
sta[j]=sta[j]*t%mod;
sta[j]=(sta[j]+c[i+l*j-1])%mod;
}
}
ll ban=0;M.clear();
for(ll j=1;j<=top;j++)
{
if(M[sta[j]]&&j-M[sta[j]]<m)
{
ban=max(ban,M[sta[j]]+m);
}
M[sta[j]]=j;
if(j>=m&&ban<=j)ans++;
}
}
printf("%lld\n",ans);
}
}
J题
LCA问题,树上三个点,问各个点统治的点个数。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int n,m;
namespace G
{
const int _=100010;
vector<int>V[_];
int fa[_][21],dep[_],siz[_];
void dfs(int u,int f)
{
for(int i=1;i<=20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
int len=V[u].size();
siz[u]=1;
for(int i=0;i<len;i++)
{
int v=V[u][i];
if(v==f)continue;
fa[v][0]=u;
dep[v]=dep[u]+1;
dfs(v,u);
siz[u]+=siz[v];
}
}
void init()
{
fa[1][0]=0;dep[1]=1;
dfs(1,0);
}
int fa_k(int u,int k)
{
for(int i=0;i<=20;i++)if(k&(1<<i))u=fa[u][i];return u;
}
int query(int a,int b)
{
if(dep[a]>dep[b])swap(a,b);
b=fa_k(b,dep[b]-dep[a]);
if(a==b)return a;
for(int i=20;i>=0;i--)
{
if(fa[a][i]!=fa[b][i])
{
a=fa[a][i];b=fa[b][i];
}
}
return fa[a][0];
}
struct STC{
int flag,u;
};
STC getMid(int a,int b,int ab)
{
int tmp=dep[a]+dep[b]-2*dep[ab];
STC t;
if(dep[a]>=dep[b])
t.flag=1,t.u=fa_k(a,(tmp-1)/2);
else
t.flag=2,t.u=fa_k(b,tmp/2);
return t;
}
int cal(int a,int b,int c,int ab,int ac)
{
STC abm=getMid(a,b,ab),acm=getMid(a,c,ac);
if(abm.flag==1&&acm.flag==1)
return dep[abm.u]>dep[acm.u]?siz[abm.u]:siz[acm.u];
else if(abm.flag==2&&acm.flag==2)
{
if (dep[abm.u]<dep[acm.u]) swap(abm,acm);
if (query(abm.u,acm.u)==acm.u) return n-siz[acm.u];
return n-siz[abm.u]-siz[acm.u];
}
else
{
if(abm.flag==2)swap(abm,acm);
int tmp=query(abm.u,acm.u);
if(tmp==abm.u)return siz[abm.u]-siz[acm.u];
else return siz[abm.u];
}
}
void Go()
{
int cas;scanf("%d",&cas);
while(cas--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)V[i].clear();
for(int i=1;i<n;i++)
{
int x,y;scanf("%d%d",&x,&y);
V[x].push_back(y);V[y].push_back(x);
}
init();
scanf("%d",&m);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int ab=query(a,b),ac=query(a,c),bc=query(b,c);
printf("%d %d %d\n",cal(a,b,c,ab,ac),cal(b,a,c,ab,bc),cal(c,a,b,ac,bc));
}
}
}
};
int main()
{
G::Go();
}
本文精选了多项算法竞赛题目并提供了详细的解决方案,包括模拟进制运算、二分查找、高斯消元、字符串哈希、LCA问题等多种算法。通过这些实战案例,展示了算法设计与实现的具体过程。
2353

被折叠的 条评论
为什么被折叠?



