以后第一题就出数学题我把出题人摁在地上打。
【题目描述】
#include
#include
#include
#include
#include
#include
#define LL long long
#define TIMES 15
using namespace std;
const int N=20005;
void fff(){
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
}
LL y,p,sum;
LL get_rand(LL n){
LL num=(((unsigned LL) rand()+100000007)*rand())%n;
return num+1;
}
LL mul(LL x,LL y,LL MOD){
LL tmp=(x*y-(LL)((long double)x/MOD*y+1e-8)*MOD)%MOD;
if (tmp<0) tmp+=MOD;
return tmp;
}
LL ksm(LL x,LL y,LL MOD){
LL ans=1;x%=MOD;
while (y){
if (y&1) ans=mul(ans,x,MOD);
x=mul(x,x,MOD);y>>=1;
}
return ans;
}
LL Mod_Mul(LL a,LL b,LL MOD){
LL msum=0;
while (b){
if(b&1) msum=(msum+a)%MOD;
b>>=1;
a=(a+a)%MOD;
}
return msum;
}
LL Quk_Mul(LL a,LL b,LL MOD){
LL qsum=1;
while (b){
if(b&1) qsum=Mod_Mul(qsum,a,MOD);
b>>=1;
a=Mod_Mul(a,a,MOD);
}
return qsum;
}
bool miller_robin(LL n){
if(n==2||n==3||n==5||n==7||n==11||n==13||n==17||n==41) return true;
if(n==1||n%2==0||n%3==0||n%5==0||n%7==0||n%11==0||n%13==0||n%41==0||n%17==0) return false;
int div2=0;
LL tn=n-1;
while (tn%2==0){
div2++;
tn/=2;
}
for (int i=1;i<=TIMES;i++){
LL x=get_rand(n-1);
if(x==1) continue;
x=Quk_Mul(x,tn,n);
LL pre=x;
for (int j=0;jif(x==1&&pre!=1&&pre!=n-1) return false;
pre=x;
}
if(x!=1) return false;
}
return true;
}
LL d[N],dminn=2e18;
int dnum;
LL gcd(LL a,LL b){
if(b==0) return a;
return gcd(b,a%b);
}
LL pollard_rho(LL dn,LL dc){
LL x,y,d,i=1,k=2;
x=get_rand(dn-1);
y=x;
while(true){
i++;
x=(Mod_Mul(x,x,dn)+dc)%dn;
d=gcd(y-x,dn);
if(1return d;
if(y==x) return dn;
if(i==k){
y=x;
k<<=1;
}
}
}
void divide(LL dn,int dk){
if(dn==1) return;
if(miller_robin(dn)==true){
d[dnum++]=dn;
dminn=min(dminn,dn);
return;
}
LL dtmp=dn;
while (dtmp>=dn) dtmp=pollard_rho(dtmp,dk--);
divide(dtmp,dk);
divide(dn/dtmp,dk);
}
LL f[N];
#define divsor d
#define dcnt dnum
void work(LL x,LL mo) {
if (x==1) {printf("%d\n",1); return;}
if (x==4) {printf("%d\n",8%mo); return;}
memset(divsor,0,sizeof divsor); dcnt=0;
if( miller_robin(y) ) divsor[++dcnt]=y;else {dcnt++;divide(x,251);}
while (divsor[dcnt]==0) dcnt--;
sort(divsor+1,divsor+dcnt+1);
for (int i=1;i<=dcnt;i++) if (divsor[i]==divsor[i-1])
{printf("-1\n"); return;} f[0]=1;
for (int i=1;i<(1<int s=0;f[i]=0;
for (int j=i;j;j-=j&(-j),s++);
for (int j=1;j<=dcnt;j++)
if (i&(1<<(j-1))) f[i]=(f[i]+mul(f[i-(1<<(j-1))],ksm(divsor[s],divsor[j]-1,mo),mo))%mo;
}
printf("%lld\n",f[(1<1]);return;
}
int main(){
srand(unsigned(time(0)));
fff();
int T;scanf("%d",&T);
while(T--){
sum=0;
scanf("%lld%lld",&y,&p);
LL n=y;
if(y==1){printf("%d\n",1%p);continue;}
if(y==4){printf("%d\n",8%p);continue;}
memset(d,0,sizeof(d));dnum=0;
if(miller_robin(n)) d[++dnum]=n;else{
dnum++;
divide(y,251);
}
while (d[dnum]==0) dnum--;
sort(d+1,d+dnum+1);
bool flag=false;
for (int i=1;i<=dnum;i++) if(d[i]==d[i-1]){printf("-1\n");flag=true;break;}
if(flag) continue;
f[0]=1;
for (int i=1;i<(1<int s=0;f[i]=0;
for (int j=i;j;j-=j&(-j),s++);
for (int j=1;j<=dnum;j++)
if(i&(1<<(j-1))) f[i]=(f[i]+mul(f[i-(1<<(j-1))],ksm(d[s],d[j]-1,p),p))%p;
}
printf("%lld\n",f[(1<1]);
}
}
【题目描述】
#include
#include
#include
#include
#include
using namespace std;
void fff(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
}
const int N=30010;
int n;
struct Edge{
int to,nxt;
}e[N*3];
int head[N],tot=0;
int read(){
int x=0;
char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
void add(int u,int v){
e[++tot].nxt=head[u];
e[tot].to=v;
head[u]=tot;
}
int val[N<<1],fa[N<<1];
bool visited[N<<1];
int dfs(int u,int y){
int sum=0;
visited[u]=true;
for (int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v!=fa[u]){
sum+=dfs(v,y);
}
}
return sum+(val[u]>y);
}
void dfs1(int u){
visited[u]=true;
for (int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!visited[v]){
fa[v]=u;
dfs1(v);
}
}
}
int main(){
fff();
n=read();
for (int i=1;iint u,v;
u=read(),v=read();
add(u,v);
add(v,u);
}
for (int i=1;i<=n;i++) val[i]=read();
memset(visited,0,sizeof(visited));
dfs1(1);
int m;
m=read();
while(m--){
int op,x,y;
op=read();
if(op==0){
x=read(),y=read();
memset(visited,false,sizeof(visited));
printf("%d\n",dfs(x,y));
}else if(op==1){
x=read(),y=read();
val[x]=y;
}else if(op==2){
x=read(),y=read();
add(x,++n);
add(n,x);
fa[n]=x;
val[n]=y;
}
}
}
附上分块的程序
#include
#include
#include
#include
#include
#define Maxn 300010
#define limit 200
using namespace std;
int n,m,u,v,last,op;char ch;
int sum1,sum2,sum3,ad1,ad2;
int w[Maxn<<1],father[Maxn<<1],rec[Maxn],nxt1[Maxn<<1],pre1[Maxn<<1],nxt2[Maxn<<1],pre2[Maxn<<1],end1[Maxn],end2[Maxn];
struct Node
{
int length,a[limit];
}B[40000];
void add1(int x,int y)
{
nxt1[++ad1]=y;pre1[ad1]=end1[x];end1[x]=ad1;
}
void add2(int x,int y)
{
nxt2[++ad2]=y;pre2[ad2]=end2[x];end2[x]=ad2;
}
inline void read(int&x)
{
ch=getchar();x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
}
void build(int u) //dfs加点,按操作op=2的方式处理孩子
{
for(int i=end1[u];i>0;i=pre1[i])
if(father[u]!=nxt1[i])
{
int T;
if(B[rec[u]].lengthelse
{
T=rec[nxt1[i]]=++sum2;
B[sum2].a[B[sum2].length++]=w[nxt1[i]];
add2(rec[u],T);
}
father[nxt1[i]]=u;sort(B[T].a,B[T].a+B[T].length);
build(nxt1[i]);
}
}
void update(int u,int v) //当块内节点更新时, 暴力重构当前块
{
int T=rec[u];
int k=lower_bound(B[T].a,B[T].a+B[T].length,w[u])-B[T].a;
B[T].a[k]=v;w[u]=v;
sort(B[T].a,B[T].a+B[T].length);
}
int bdfs(int u,int x) //树上块查询
{
int sum=B[u].length-(upper_bound(B[u].a,B[u].a+B[u].length,x)-B[u].a);
for(int i=end2[u];i>0;i=pre2[i])
sum+=bdfs(nxt2[i], x);
return sum;
}
int pdfs(int u, int x) //树上点查询
{
int sum=0;
if(w[u]>x) sum++;
for(int i=end1[u];i>0;i=pre1[i])
if(nxt1[i]!=father[u])
{
if(rec[u]==rec[nxt1[i]]) sum+=pdfs(nxt1[i],x);
else sum+=bdfs(rec[nxt1[i]],x);
}
return sum;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
read(n);
for(int i=1;ifor(int i=1;i<=n;i++) read(w[i]);
father[1]=0;
B[++sum2].length=1;
B[sum2].a[0]=w[1];
rec[1]=sum2;
build(1);
read(m);
while (m--)
{
read(op);read(u);read(v);
if(op==0) last=pdfs(u,v),printf("%d\n",last);
if(op==1) update(u,v);
if(op==2)
{
w[++n]=v;
add1(u,n);
father[n]=u;
int T=rec[u];
if(B[T].lengthelse T=++sum2,B[T].a[B[T].length++]=v,add2(rec[u],sum2),rec[n]=sum2; //添加新的块
sort(B[T].a,B[T].a+B[T].length); //暴力构建状态
}
}
}
【题目描述】
我们把上面的方程改变一下,变成
我们考虑将(D[i],f[i])放到坐标系中。则最优解即为一条以V[i]为斜率的点从x轴下的无限远处向上平移所得到的第一个点。凸包解决
#include
#include
#include
#include
#include
#include
#define LL long long
using namespace std;
void fff(){
freopen("town.in","r",stdin);
freopen("town.out","w",stdout);
}
const int N=100100;
int n,end,w;
int a_val[N],b_val[N];
#define x first
#define y second
vector int ,int> > G[N];
LL d[N],f[N],q[N];
struct STACK{
int k,x,fa,dep,_pos,_val,_end;
}s[N];
double get_k(int j,int k){
return (double)(f[k]-f[j])/(d[k]-d[j]);
}
int search(int vv){
int l=0,r=end-2;
while(lint mid=(l+r+1)>>1;
if(get_k(q[mid],q[mid+1])else r=mid-1;
}
return q[l+1];
}
void inst(int l,int r,int &_pos,int &_val,int x){
while (lint mid=(l+r+1)>>1;
if(get_k(q[mid-1],q[mid])1],x)) l=mid;else r=mid-1;
}
if(get_k(q[l-1],q[l])>get_k(q[l-1],x)) l--;
_pos=l+1,_val=q[_pos];
end=l+2,q[end-1]=x;
}
void work(){
memset(s,0,sizeof(s));
w=1;s[w].fa=s[w].k=-1;
while (w){
int x=s[w].x,fa=s[w].fa,dep=s[w].dep;
int &k=s[w].k,&_pos=s[w]._pos,&_val=s[w]._val,&_end=s[w]._end;
if(k==-1){
d[x]=dep,f[x]=a_val[x]+1ll*dep*b_val[x];_end=end;
if(end>1){
int p=q[0];
if(get_k(q[0],q[1])1ll*b_val[x]*(dep-d[p])));
inst(1,end-1,_pos,_val,x);
}else _pos=end,_val=q[_pos],q[end++]=x;
++k;
}else{
if(kif(G[x][k].x!=fa) s[++w].x=G[x][k].x,s[w].fa=x,s[w].dep=dep+G[x][k].y,s[w].k=-1;
++k;
}else end=_end,q[_pos]=_val,--w;
}
}
}
int main(){
fff();
scanf("%d",&n);
for (int i=1;iint u,v,w;
scanf("%d%d%d",&u,&v,&w);
G[u-1].push_back(make_pair(v-1,w));
G[v-1].push_back(make_pair(u-1,w));
}
for (int i=1;iscanf("%d%d",&a_val[i],&b_val[i]);
work();
for (int i=1;iprintf("%lld ",f[i]);
return 0;
}