Shoi2017(六省聯考)Day1題解
阿新 • • 發佈:2019-01-22
終於發現自己是真殘了(我這句話都說了幾遍了QAQ)
T1:容易發現答案只與最後一科出成績的時間有關,列舉這個時間,然後按順序維護代價就行了。
BZ上的資料範圍不對,不過影響不大,但是有一個特別坑比的點是
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#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]<i)
++p;
t+=p-1;
re+=t*C;
while(q<=m && b[q]<i)
++q;
r-=m-q+1 ;
l+=q-1;
if(B<A)
re+=B*r;
else
re+=A*min(l,r)+B*max(r-l,0ll);
ans=min(ans,re);
#ifndef ONLINE_JUDGE
cout<<t<<' '<<l<<' '<<r<<' '<<re<<endl;
#endif
}
cout<<ans<<endl;
return 0;
}
T2:
這……
這……
這不是上帝與集合的……
正確用法……
嗎??
需要用到這樣一個引理:
當
這個引理不需要
然後就簡單了,因為
預處理每個數進行log次操作後的結果,利用線段樹維護區間和,以及區間內是否都不動了,就行了
時間複雜度
為了卡常數我LOG只開了15實際上至少要開26以上才能保證正確……所以別HACK我程式碼拜託
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#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(power<p)
return 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;i<LOG;i++)
phi[i]=Phi(phi[i-1]);
for(int i=1;i<=n;i++)
{
static int power[LOG];
power[0]=a[i];
for(int j=1;j<LOG;j++)
power[j]=Fake_Quick_Power(c,power[j-1]);
for(int j=1;j<LOG;j++)
next[i][j]=Calculate(j,phi[0],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:看那個組合數的直觀含義就是
矩陣乘法加速轉移,沒了……
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#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;i<k;i++)
a[i][i]=flag;
}
int* 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;i<k;i++)
for(int j=0;j<k;j++)
for(int kk=0;kk<k;kk++)
(z[i][j]+=(long 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;i<k;i++)
x[i][i]++,x[(i+k-1)%k][i]++;
x=Quick_Power(x,(long long)n*k);
cout<<x[0][r]<<endl;
return 0;
}