终于发现自己是真残了(我这句话都说了几遍了QAQ)
T1:容易发现答案只与最后一科出成绩的时间有关,枚举这个时间,然后按顺序维护代价就行了。
BZ上的数据范围不对,不过影响不大,但是有一个特别坑比的点是 C=1016 ,为了这个SB点卡了俩小时气都气死了
#include
#include
#include
#include
#define M 100100
using namespace std;
int A,B;
long long C;
int n,m;
int a[M],b[M];
long long ans=0x3f3f3f3f3f3f3f3fll;
int main()
{
cin>>A>>B>>C;
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
sort(b+1,b+m+1);
int p=1,q=1;
long long t=0;
long long l=0,r=0;
for(int i=1;i<=m;i++)
r+=b[i];
for(int i=1;i<=(C==10000000000000000ll?a[1]:b[m]);i++)
{
long long re=0;
while(p<=n && a[p]1;
re+=t*C;
while(q<=m && b[q]1;
l+=q-1;
if(Belse
re+=A*min(l,r)+B*max(r-l,0ll);
ans=min(ans,re);
#ifndef ONLINE_JUDGE
cout<' '<' '<' '<#endif
}
cout<return 0;
}
T2:
这……
这……
这不是上帝与集合的……
正确用法……
吗??
需要用到这样一个引理:
当 a≥φ(p) 时, xa≡xa mod φ(p)+φ(p)(mod p)
这个引理不需要 (a,p)=1 就能用!
然后就简单了,因为 p 最多 φ log次就会变成1,所以根据这个引理可以看出来,一个数最多进行log次操作就不动了
预处理每个数进行log次操作后的结果,利用线段树维护区间和,以及区间内是否都不动了,就行了
时间复杂度 O(nlog3p+mlognlogp)
为了卡常数我LOG只开了15实际上至少要开26以上才能保证正确……所以别HACK我代码拜托
#include
#include
#include
#include
#include
#define M 50500
#define LOG 15
using namespace std;
int n,m,p,c;
int a[M];
int phi[LOG];
int next[M][LOG],now[M];
struct Segment_Tree
{
Segment_Tree *ls,*rs;
int sum;
bool flag;
friend void* operator new(size_t)
{
static Segment_Tree mempool[M<<1],*C=mempool;
return C++;
}
void Update()
{
sum=(ls->sum+rs->sum)%p;
flag=ls->flag&rs->flag;
}
void Build_Tree(int l,int r)
{
int mid=(l+r)>>1;
if(l==r)
{
sum=a[mid];
return ;
}
(ls=new Segment_Tree)->Build_Tree(l,mid);
(rs=new Segment_Tree)->Build_Tree(mid+1,r);
Update();
}
void Modify(int l,int r,int x,int y)
{
//printf("Modify:%d %d %d %d\n",l,r,x,y);
int mid=(l+r)>>1;
if(flag) return;
if(l==r)
{
sum=next[mid][++now[mid]];
if(now[mid]==LOG-1)
flag=true;
return ;
}
if(x==l&&y==r)
{
ls->Modify(l,mid,x,mid);
rs->Modify(mid+1,r,mid+1,y);
Update();
return ;
}
if(y<=mid)
ls->Modify(l,mid,x,y);
else if(x>mid)
rs->Modify(mid+1,r,x,y);
else
ls->Modify(l,mid,x,mid),rs->Modify(mid+1,r,mid+1,y);
Update();
}
int Query(int l,int r,int x,int y)
{
int mid=(l+r)>>1;
if(x==l&&y==r)
return sum;
if(y<=mid)
return ls->Query(l,mid,x,y);
if(x>mid)
return rs->Query(mid+1,r,x,y);
return (ls->Query(l,mid,x,mid)+rs->Query(mid+1,r,mid+1,y))%p;
}
}*root=new Segment_Tree;
int Phi(int n)
{
int re=n;
for(int i=2;i*i<=n;i++)
if(n%i==0)
{
re/=i;
re*=i-1;
while(n%i==0)
n/=i;
}
if(n^1) re/=n,re*=n-1;
return re;
}
int Fake_Quick_Power(long long x,int y)
{
long long re=1;
if(y>p) return p+1;
while(y)
{
if(y&1)
{
re*=x;
if(re>p)
return p+1;
}
x*=x;
if(x>p)
return p+1;
y>>=1;
}
return re;
}
int Quick_Power(long long x,int y,int mod)
{
long long re=1;
while(y)
{
if(y&1) (re*=x)%=mod;
(x*=x)%=mod; y>>=1;
}
return re;
}
int Calculate(int c_cnt,int &mod,int &power)
{
if(mod==1)
return 0;
if(powerreturn power%mod;
//if(*(&power-1)<*(&mod+1))
// return Quick_Power(c,*(&power-1),mod);
return Quick_Power(c,Calculate(c_cnt-1,*(&mod+1),*(&power-1))+*(&mod+1),mod);
}
int main()
{
cin>>n>>m>>p>>c;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
phi[0]=p;
for(int i=1;i1]);
for(int i=1;i<=n;i++)
{
static int power[LOG];
power[0]=a[i];
for(int j=1;j1]);
for(int j=1;j0],power[j]);
}
root->Build_Tree(1,n);
for(int i=1,type,l,r;i<=m;i++)
{
scanf("%d%d%d",&type,&l,&r);
if(type==0)
root->Modify(1,n,l,r);
else
printf("%d\n",root->Query(1,n,l,r));
}
return 0;
}
T3:看那个组合数的直观含义就是 nk 个球里面取 m 个, m%k=r 的方案数
f[i][j] 表示 i 个球里面取 m 个, m%k=j 的方案数,则 f[i][j]=f[i−1][j]+f[i−1][(j−1)%k]
矩阵乘法加速转移,没了……
#include
#include
#include
#include
#define M 55
using namespace std;
int n,p,k,r;
struct Matrix
{
int a[M][M];
Matrix(bool flag=false)
{
memset(a,0,sizeof a);
for(int i=0;iint* operator [] (int i)
{
return a[i];
}
const int* operator [] (int i) const
{
return a[i];
}
friend Matrix operator * (const Matrix &x,const Matrix &y)
{
Matrix z(0);
for(int i=0;ifor(int j=0;jfor(int kk=0;kklong long)x[i][kk]*y[kk][j]%p)%=p;
return z;
}
friend Matrix Quick_Power(Matrix x,long long y)
{
Matrix re(1);
while(y)
{
if(y&1) re=re*x;
x=x*x; y>>=1;
}
return re;
}
};
int main()
{
cin>>n>>p>>k>>r;
Matrix x(false);
for(int i=0;i1)%k][i]++;
x=Quick_Power(x,(long long)n*k);
cout<0][r]<return 0;
}