题解戳这里
4002 有意义的字符串:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define P 7528443412579576937ull
using namespace std;
typedef unsigned long long ull;
ull b,d,n;
ull Times(ull x,ull y)
{
ull re=0;
while(y)
{
if(y&1)
{
re+=x;
if(re>=P)
re-=P;
}
x+=x;
if(x>=P)
x-=P;
y>>=1;
}
return re;
}
namespace Matrix_Multiplication{
struct Matrix{
ull a[2][2];
ull* operator [] (int x)
{
return a[x];
}
friend Matrix& operator *= (Matrix &x,Matrix y)
{
int i,j,k;
Matrix z;
memset(&z,0,sizeof z);
for(i=0;i<2;i++)
for(j=0;j<2;j++)
for(k=0;k<2;k++)
(z[i][j]+=Times(x[i][k],y[k][j]))%=P;
return x=z;
}
}a;
//a[i]=b*a[i-1]+(d-b*b)/4*a[i-2]
//a[0]=2,a[1]=b
Matrix Quick_Power(Matrix x,ull y)
{
Matrix re;
re[0][0]=re[1][1]=1;
re[1][0]=re[0][1]=0;
while(y)
{
if(y&1) re*=x;
x*=x; y>>=1;
}
return re;
}
}
int main()
{
using namespace Matrix_Multiplication;
cin>>b>>d>>n;
a[0][0]=0;
a[1][0]=1;
a[0][1]=d-b*b>>2;
a[1][1]=b;
Matrix ans=Quick_Power(a,n);
cout<<(Times(ans[0][0],2)+Times(ans[1][0],b)-(d!=b*b&&~n&1))%P<<endl;
return 0;
}
4003 城池攻占:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 300300
using namespace std;
struct Heap{
#define HEIGHT(p) ((p)?(p)->height:0)
Heap *ls,*rs;
long long height,val,belong;
long long times_mark,add_mark;
void* operator new(size_t,long long _,long long __)
{
static Heap mempool[M],*C=mempool;
C->ls=C->rs=0x0;
C->height=1;
C->val=_;
C->belong=__;
C->times_mark=1;
C->add_mark=0;
return C++;
}
void Times(long long x)
{
val*=x;
times_mark*=x;
add_mark*=x;
}
void Add(long long x)
{
val+=x;
add_mark+=x;
}
void Push_Down()
{
if(times_mark!=1)
{
if(ls) ls->Times(times_mark);
if(rs) rs->Times(times_mark);
times_mark=1;
}
if(add_mark!=0)
{
if(ls) ls->Add(add_mark);
if(rs) rs->Add(add_mark);
add_mark=0;
}
}
void Push_Up()
{
height=HEIGHT(rs)+1;
}
friend Heap* Merge(Heap *x,Heap *y)
{
if(!x) return y;
if(!y) return x;
if(x->val>y->val)
swap(x,y);
x->Push_Down();
x->rs=Merge(x->rs,y);
if( HEIGHT(x->rs)>HEIGHT(x->ls) )
swap(x->ls,x->rs);
x->Push_Up();
return x;
}
}*heap[M];
struct abcd{
int to,next;
}table[M];
int head[M],tot;
int n,m;
int fa[M],dpt[M],ans[M];
long long h[M],a[M],v[M];
int st[M],ed[M];
void Add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
void Tree_DP()
{
static int q[M],r,h;
int i,j;
q[++r]=1;
while(r!=h)
{
int x=q[++h];
dpt[x]=dpt[fa[x]]+1;
for(i=head[x];i;i=table[i].next)
q[++r]=table[i].to;
}
for(j=n;j;j--)
{
int x=q[j];
for(i=head[x];i;i=table[i].next)
heap[x]=Merge(heap[x],heap[table[i].to]);
while( heap[x] && heap[x]->val< ::h[x] )
{
ed[heap[x]->belong]=x;
ans[x]++;
heap[x]->Push_Down();
heap[x]=Merge(heap[x]->ls,heap[x]->rs);
}
if(heap[x])
{
if(a[x]==0)
heap[x]->Add(v[x]);
else
heap[x]->Times(v[x]);
}
}
}
int main()
{
int i;long long x,y;
cin>>n>>m;
for(i=1;i<=n;i++)
scanf("%lld",&h[i]);
for(i=2;i<=n;i++)
{
scanf("%d%lld%lld",&fa[i],&a[i],&v[i]);
Add(fa[i],i);
}
for(i=1;i<=m;i++)
{
scanf("%lld%lld",&x,&y);
Heap *temp=new (x,i)Heap;
st[i]=y;heap[y]=Merge(temp,heap[y]);
}
Tree_DP();
for(i=1;i<=n;i++)
printf("%d\n",ans[i]);
for(i=1;i<=m;i++)
printf("%d\n",dpt[st[i]]-dpt[ed[i]]);
return 0;
}
4004 装备购买:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 550
#define MOD 999911659
using namespace std;
int n,m,cnt;
long long ans;
long long Quick_Power(long long x,long long y)
{
long long re=1;
while(y)
{
if(y&1) (re*=x)%=MOD;
(x*=x)%=MOD; y>>=1;
}
return re;
}
struct Vector{
long long a[M];
friend istream& operator >> (istream &_,Vector &v)
{
int i;
for(i=1;i<=m;i++)
scanf("%I64d",&v.a[i]);
return _;
}
void Elimination(const Vector &v,int pos)
{
int i;
long long temp=(MOD-a[pos]*Quick_Power(v.a[pos],MOD-2)%MOD)%MOD;
for(i=pos;i<=m;i++)
(a[i]+=temp*v.a[i])%=MOD;
}
bool operator < (const Vector &v) const
{
return false;
}
}*linear_bases[M];
pair<int,Vector> a[M];
bool Insert(Vector &v)
{
int i;
for(i=1;i<=m;i++)
if(v.a[i])
{
if(!linear_bases[i])
{
linear_bases[i]=&v;
return true;
}
v.Elimination(*linear_bases[i],i);
}
return false;
}
int main()
{
int i;
cin>>n>>m;
for(i=1;i<=n;i++)
cin>>a[i].second;
for(i=1;i<=n;i++)
scanf("%d",&a[i].first);
sort(a+1,a+n+1);
for(i=1;i<=n;i++)
if(Insert(a[i].second))
++cnt,ans+=a[i].first;
cout<<cnt<<‘ ‘<<ans<<endl;
return 0;
}
4005 骗我呢:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 3003003
#define MOD 1000000007
using namespace std;
int n,m;
long long fac[M],inv[M],ans;
void Linear_Shaker()
{
int i;
for(fac[0]=1,i=1;i<=3000000;i++)
fac[i]=fac[i-1]*i%MOD;
for(inv[1]=1,i=2;i<=3000000;i++)
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
for(inv[0]=1,i=1;i<=3000000;i++)
(inv[i]*=inv[i-1])%=MOD;
}
long long C(int n,int m)
{
if(n<m) return 0;
return fac[n] * inv[m] % MOD * inv[n-m] % MOD ;
}
long long Calculate(int x,int y)
{
if(x<0||y<0)
return 0;
return C(x+y,x);
}
void Flip1(int &x,int &y)//沿着直线y=x+1翻转
{
swap(x,y);
x--;y++;
}
void Flip2(int &x,int &y)//沿着直线y=x-(m+2)翻转
{
swap(x,y);
x+=m+2;y-=m+2;
}
int main()
{
cin>>n>>m;
Linear_Shaker();
ans=Calculate(m+n+1,n);
int x=m+n+1,y=n;
while(x>=0&&y>=0)
{
Flip1(x,y);
ans-=Calculate(x,y);
Flip2(x,y);
ans+=Calculate(x,y);
ans%=MOD;
}
x=m+n+1,y=n;
while(x>=0&&y>=0)
{
Flip2(x,y);
ans-=Calculate(x,y);
Flip1(x,y);
ans+=Calculate(x,y);
ans%=MOD;
}
cout<<(ans+MOD)%MOD<<endl;
return 0;
}
4006 管道连接:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1010
using namespace std;
struct Key_Point{
int color,point;
bool operator < (const Key_Point &k) const
{
return color < k.color ;
}
}points[20],_points[20];
struct abcd{
int to,f,next;
}table[3030<<1];
int head[M],tot;
int n,m,p,c,cnt;
int f[1024][M],g[32];
int q[65540];
unsigned short r,h;
void Add(int x,int y,int z)
{
table[++tot].to=y;
table[tot].f=z;
table[tot].next=head[x];
head[x]=tot;
}
void SPFA(int f[])
{
static bool v[M];
int i;
while(r!=h)
{
int x=q[++h];v[x]=false;
for(i=head[x];i;i=table[i].next)
if(f[table[i].to]>f[x]+table[i].f)
{
f[table[i].to]=f[x]+table[i].f;
if(!v[table[i].to])
v[table[i].to]=true,q[++r]=table[i].to;
}
}
}
int Steiner_Tree()
{
int i,j,k;
for(i=1;i<1<<cnt;i++)
{
for(j=1;j<=n;j++)
{
for(k=i&(i-1);k;(--k)&=i)
f[i][j]=min(f[i][j],f[k][j]+f[i^k][j]);
if(f[i][j]!=0x3f3f3f3f)
q[++r]=j;
}
SPFA(f[i]);
}
int ans=0x3f3f3f3f;
for(i=1;i<=n;i++)
ans=min(ans,f[(1<<cnt)-1][i]);
return ans;
}
int main()
{
int i,j,x,y,z;
cin>>n>>m>>p;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
Add(x,y,z);Add(y,x,z);
}
for(i=1;i<=p;i++)
scanf("%d%d",&points[i].color,&points[i].point);
sort(points+1,points+p+1);
p=0;
for(i=1;points[i].color;i++)
if(points[i].color==points[i-1].color||points[i].color==points[i+1].color)
_points[++p]=points[i];
memcpy(points,_points,sizeof points);
for(i=1;i<=p;i++)
{
if(i==1||_points[i].color!=_points[i-1].color)
++c;
points[i].color=c;
}
memset(g,0x3f,sizeof g);
for(i=1;i<1<<c;i++)
{
cnt=0;
for(j=1;j<=p;j++)
if(i&(1<<points[j].color-1))
++cnt;
memset(f,0x3f,sizeof(f[0][0])*M*(1<<cnt));
cnt=0;
for(j=1;j<=p;j++)
if(i&(1<<points[j].color-1))
f[1<<cnt++][points[j].point]=0;
g[i]=Steiner_Tree();
}
for(i=1;i<1<<c;i++)
for(j=i&(i-1);j;(--j)&=i)
g[i]=min(g[i],g[j]+g[i^j]);
cout<<g[(1<<c)-1]<<endl;
return 0;
}
4007 战争调度:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1100
using namespace std;
int n,m;
int a[M][M],b[M][M],f[M][M];
//f[i][j]表示以i为根的子树中选择j个参战的最大收益
bool status[M];
void DFS(int x,int size)
{
int i,j;
if(x>=1<<n-1)
{
f[x][0]=f[x][1]=0;
for(i=x>>1;i;i>>=1)
if(status[i]==0)
f[x][1]+=a[x][i];
else
f[x][0]+=b[x][i];
return ;
}
status[x]=false;
DFS(x<<1,size>>1);DFS(x<<1|1,size>>1);
int limit=min(size,m);//x所在的子树中最多有limit个平民参战
memset(f[x],0,sizeof(f[0][0])*(limit+1));
for(i=0;i<=limit;i++)
{
int upper=min(size>>1,i);//左子树最多有upper个平民参战
int lower=max(i-(size>>1),0);//左子树最少有lower个平民参战
for(j=lower;j<=upper;j++)
f[x][i]=max(f[x][i],f[x<<1][j]+f[x<<1|1][i-j]);
}
status[x]=true;
DFS(x<<1,size>>1);DFS(x<<1|1,size>>1);
for(i=0;i<=limit;i++)
{
int upper=min(size>>1,i);//左子树最多有upper个平民参战
int lower=max(i-(size>>1),0);//左子树最少有lower个平民参战
for(j=lower;j<=upper;j++)
f[x][i]=max(f[x][i],f[x<<1][j]+f[x<<1|1][i-j]);
}
}
int main()
{
int i,j;
cin>>n>>m;
for(i=1<<n-1;i<1<<n;i++)
for(j=i>>1;j;j>>=1)
scanf("%d",&a[i][j]);
for(i=1<<n-1;i<1<<n;i++)
for(j=i>>1;j;j>>=1)
scanf("%d",&b[i][j]);
DFS(1,1<<n-1);
int ans=0;
for(i=0;i<=m;i++)
ans=max(ans,f[1][i]);
cout<<ans<<endl;
}
原文:http://blog.csdn.net/popoqqq/article/details/45169289