2020_10_05:
A.没意思。

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 const ll inf=1E18; 5 int n,m,totC; 6 ll f[2005*50],g[2005*50]; 7 struct pt 8 { 9 int type,c; 10 ll w,v; 11 bool operator<(const pt&A)const 12 { 13 return w==A.w?type<A.type:w<A.w; 14 } 15 }a[4005]; 16 inline void solve() 17 { 18 sort(a+1,a+n+m+1); 19 for(int i=0;i<=totC;++i) 20 f[i]=-inf; 21 f[0]=0; 22 int tot=0; 23 for(int i=n+m;i>=1;--i) 24 if(a[i].type==0) 25 { 26 int c=a[i].c,v=a[i].v; 27 for(int j=0;j<=tot-c;++j) 28 f[j]=max(f[j],f[j+c]+v); 29 } 30 else 31 { 32 int c=a[i].c,v=a[i].v; 33 tot+=c; 34 for(int j=tot;j>=c;--j) 35 f[j]=max(f[j],f[j-c]-v); 36 } 37 ll ans=-inf; 38 for(int i=0;i<=totC;++i) 39 ans=max(ans,f[i]); 40 cout<<ans<<endl; 41 } 42 int main() 43 { 44 // freopen("a.in","r",stdin); 45 // ios::sync_with_stdio(false); 46 cin>>n>>m; 47 for(int i=1;i<=n;++i) 48 { 49 cin>>a[i].c>>a[i].w>>a[i].v; 50 totC+=a[i].c; 51 a[i].type=1; 52 } 53 for(int i=n+1;i<=n+m;++i) 54 { 55 cin>>a[i].c>>a[i].w>>a[i].v; 56 a[i].type=0; 57 } 58 solve(); 59 return 0; 60 }
B.将一个数平方后取模很快(24次)就能找到循环节,维护循环节即可。
map是真的慢!!!以后可以认为map、unordered_map的常数是远大于40的。

1 #include<bits/stdc++.h> 2 #define mod 998244353 3 using namespace std; 4 typedef long long int ll; 5 const int maxn=2E5+5; 6 int n,m,tag[maxn*4]; 7 ll a[maxn]; 8 int loop[maxn*4][24],rem[maxn*4],hh[maxn]; 9 bool ok[maxn*4]; 10 inline int read() 11 { 12 char ch=getchar(); 13 while(!isdigit(ch))ch=getchar(); 14 int s=ch-'0';ch=getchar(); 15 while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} 16 return s; 17 } 18 int G[55]; 19 inline void write(int x) 20 { 21 int g=0; 22 do{G[++g]=x%10;x/=10;}while(x); 23 for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar(' '); 24 } 25 ll tmp[24]; 26 inline void put(int num,int x) 27 { 28 tag[num]+=x; 29 for(int i=0;i<24;++i) 30 tmp[i]=loop[num][(i+x)%24]; 31 for(int i=0;i<24;++i) 32 loop[num][i]=tmp[i]; 33 rem[num]=loop[num][0]; 34 } 35 inline void pushup(int num) 36 { 37 ok[num]=ok[num<<1]&ok[num<<1|1]; 38 rem[num]=rem[num<<1]+rem[num<<1|1]; 39 rem[num]-=rem[num]>=mod?mod:0; 40 if(ok[num]) 41 { 42 for(int i=0;i<24;++i) 43 loop[num][i]=loop[num<<1][i]+loop[num<<1|1][i]; 44 for(int i=0;i<24;++i) 45 loop[num][i]-=loop[num][i]>=mod?mod:0; 46 } 47 } 48 inline void pushdown(int num) 49 { 50 int x=tag[num]; 51 if(x==0) 52 return; 53 tag[num]=0; 54 put(num<<1,x),put(num<<1|1,x); 55 } 56 void build(int l,int r,int num) 57 { 58 if(l==r) 59 { 60 hh[l]=24; 61 rem[num]=a[l]; 62 return; 63 } 64 int mid=(l+r)>>1; 65 build(l,mid,num<<1),build(mid+1,r,num<<1|1); 66 pushup(num); 67 } 68 void change(int L,int R,int l,int r,int num) 69 { 70 if(L<=l&&r<=R&&ok[num]) 71 { 72 put(num,1); 73 return; 74 } 75 if(l==r) 76 { 77 a[l]=a[l]*a[l]%mod; 78 --hh[l]; 79 if(hh[l]==0) 80 { 81 ok[num]=1; 82 ll x=a[l]; 83 for(int i=0;i<24;++i,x=x*x%mod) 84 loop[num][i]=x; 85 } 86 rem[num]=a[l]; 87 return; 88 } 89 pushdown(num); 90 int mid=(l+r)>>1; 91 if(R<=mid) 92 change(L,R,l,mid,num<<1); 93 else if(mid<L) 94 change(L,R,mid+1,r,num<<1|1); 95 else 96 change(L,R,l,mid,num<<1),change(L,R,mid+1,r,num<<1|1); 97 pushup(num); 98 } 99 ll ask(int L,int R,int l,int r,int num) 100 { 101 if(L<=l&&r<=R) 102 return rem[num]; 103 pushdown(num); 104 int mid=(l+r)>>1; 105 if(R<=mid) 106 return ask(L,R,l,mid,num<<1); 107 else if(mid<L) 108 return ask(L,R,mid+1,r,num<<1|1); 109 return ask(L,R,l,mid,num<<1)+ask(L,R,mid+1,r,num<<1|1); 110 } 111 int main() 112 { 113 // freopen("nagato2.in","r",stdin); 114 // freopen("a.out","w",stdout); 115 ios::sync_with_stdio(false); 116 n=read(),m=read(); 117 for(int i=1;i<=n;++i) 118 a[i]=read(); 119 build(1,n,1); 120 while(m--) 121 { 122 int opt=read(),l=read(),r=read(); 123 if(opt==1) 124 change(l,r,1,n,1); 125 else 126 write(ask(l,r,1,n,1)%mod); 127 } 128 return 0; 129 }
2020_10_06:
A.找寻环节,模拟即可。

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 int n,a[605][605]; 5 int tot,wait[605*605]; 6 int vis[605][605]; 7 ll d; 8 int main() 9 { 10 // freopen("speech3.in","r",stdin); 11 ios::sync_with_stdio(false); 12 cin>>n>>d; 13 for(int i=1;i<=n;++i) 14 for(int j=1;j<=n;++j) 15 cin>>a[i][j]; 16 int u=1,v=2; 17 for(ll i=1;i<=d;++i) 18 { 19 if(vis[u][v]) 20 { 21 int len=i-vis[u][v]; 22 ll left=(d-i+1)%len; 23 if(left==0) 24 cout<<wait[vis[u][v]-1+len]<<endl; 25 else 26 cout<<wait[vis[u][v]-1+left]<<endl; 27 return 0; 28 } 29 wait[++tot]=u; 30 vis[u][v]=i; 31 int w=a[v][u]; 32 u=v; 33 v=w; 34 } 35 cout<<wait[tot]<<endl; 36 return 0; 37 }
B.
首先,最简单的想法是设f[i][j]表示a序列中到了第i位,b序列中到了第j位的最小代价,简单转移即可。
但发现数据范围实在是太大了,这种情况下通常的想法是找到转移的规律或者是减少状态数。
首先,f[i][j]的第二维可以省略:我们现在a序列和b序列后新增一个很大的数字(n+1),那么我们只需要考虑a[i]在b序列中出现的位置。令f[i]表示考虑a序列到了第i位的最小代价。那么f[i]=min{f[j]+cost(j+1,i)},其中a[j]和a[i]在b序列中是相邻的。cost(l+1,r)可以分两类考虑:一种是a[i]小于0的,显然会直接加在答案里;一种是a[i]大于等于b[j]且大于0的,那么一定也会被加在答案里。前者可以前缀和快速算出,后者可以用树状数组得出。这样的复杂度是O(nlogn)的。
注意到所有数字的值域也是线性的,我们尝试把某些贡献往后移动。具体来说,如果当前决策的数字分别为b[j]和b[i](j<i),那么对于上面的第二种贡献,我们改为统计 大于等于b[j]且小于b[i]且大于0的数字之和,而不考虑它的下标是否在[l,r]中。这显然是对的。具体实现看代码。复杂度为O(n+值域)。

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 const int maxn=5E6+5;//?!?!?! 5 const ll inf=1E18; 6 int n,m,a[maxn],b[maxn],what[maxn],q[maxn]; 7 ll f[maxn],g[maxn],h[maxn],val[maxn]; 8 inline char gc() 9 { 10 static char now[1<<20],*S,*T; 11 if (T==S) 12 { 13 T=(S=now)+fread(now,1,1<<20,stdin); 14 if (T==S) return EOF; 15 } 16 return *S++; 17 }//getchar 18 inline int read() 19 { 20 int res=0,sign=1; 21 char c; 22 while ((c=gc())<'0'||c>'9') if (c=='-') sign=-1; 23 res=(c^48); 24 while ((c=gc())>='0'&&c<='9') res=(res<<3)+(res<<1)+(c^48); 25 return res*sign; 26 }//read a signed interger 27 int main() 28 { 29 // freopen("offa6.in","r",stdin); 30 n=read(); 31 for(int i=1;i<=n;++i) 32 a[i]=read(); 33 for(int i=1;i<=n;++i) 34 val[i]=read(); 35 m=read(); 36 for(int i=1;i<=m;++i) 37 { 38 b[i]=read(); 39 what[b[i]]=i; 40 } 41 n+=1,m+=1; 42 a[n]=n,b[m]=n; 43 what[n]=m; 44 for(int i=0;i<=m;++i) 45 g[i]=inf; 46 ll now=inf,x=0; 47 g[0]=0; 48 for(int i=1,j=1;i<=n;q[i++]=j) 49 if(b[j]<i) 50 ++j; 51 for(int i=1;i<=n;++i) 52 { 53 int pos=what[a[i]]; 54 if(pos) 55 f[i]=(g[pos-1]<now)?g[pos-1]+h[pos]+x:now; 56 if(val[i]>=0) 57 h[q[a[i]]]+=val[i]; 58 else 59 x+=val[i]; 60 if(pos&&f[i]<now) 61 g[pos]=min(g[pos],f[i]-x); 62 } 63 if(f[n]<now) 64 cout<<f[n]<<endl; 65 else 66 cout<<"Impossible"<<endl; 67 return 0; 68 }
C.
首先计算出从节点u经过一条边走到节点v的期望时间,那么对于一条路径,时间为经过的路径的权值之和。这个要么推式子,要么感性理解,要么打表找规律。
以1为根后,一条路径的权值为((u->1)+(1->v)-(lca(u,v)->1+1->lca(u,v)))。m次方需要记录一个子树中的0~m次方的分别的和。想怎么算就怎么算。
要优化当然上ntt了。

1 #include<bits/stdc++.h> 2 #define mod 998244353 3 using namespace std; 4 typedef long long int ll; 5 const int maxn=3E4+5; 6 int n,m; 7 int size,head[maxn]; 8 ll up[maxn],down[maxn],sum[maxn],C[51][51]; 9 ll f[maxn][51],g[maxn][51]; 10 struct edge 11 { 12 int to,next; 13 }E[maxn*2]; 14 inline void add(int u,int v) 15 { 16 E[++size].to=v; 17 E[size].next=head[u]; 18 head[u]=size; 19 } 20 inline ll qpow(ll x,ll y) 21 { 22 ll ans=1,base=x; 23 while(y) 24 { 25 if(y&1) 26 ans=ans*base%mod; 27 base=base*base%mod; 28 y>>=1; 29 } 30 return ans; 31 } 32 inline void init() 33 { 34 C[0][0]=1; 35 for(int i=1;i<=50;++i) 36 { 37 C[i][0]=1; 38 for(int j=1;j<=i;++j) 39 C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; 40 } 41 } 42 void dfs1(int u,int F) 43 { 44 down[u]=0; 45 ll s=0; 46 sum[u]=1; 47 for(int i=head[u];i;i=E[i].next) 48 { 49 int v=E[i].to; 50 if(v==F) 51 continue; 52 dfs1(v,u); 53 sum[u]+=sum[v]; 54 s+=up[v]+1; 55 } 56 up[u]=(s+1)%mod; 57 } 58 ll ans; 59 void dfs2(int u,int F,ll d1,ll d2,ll d3) 60 { 61 d1=(d1+up[u])%mod; 62 d3=(d2+d3)%mod; 63 up[u]=d1; 64 down[u]=d3; 65 ll s=1+d2; 66 if(F==0) 67 s-=1; 68 for(int i=head[u];i;i=E[i].next) 69 { 70 int v=E[i].to; 71 if(v==F) 72 continue; 73 s+=1+up[v]; 74 } 75 for(int i=head[u];i;i=E[i].next) 76 { 77 int v=E[i].to; 78 if(v==F) 79 continue; 80 dfs2(v,u,d1,(s-up[v]+mod)%mod,d3); 81 } 82 } 83 void dfs3(int u,int F) 84 { 85 ll tmp[51]; 86 tmp[0]=1; 87 for(int i=1;i<=m;++i) 88 tmp[i]=-tmp[i-1]*(up[u]+down[u])%mod; 89 for(int i=0;i<=m;++i) 90 f[u][i]=qpow(up[u],i),g[u][i]=qpow(down[u],i); 91 for(int e=head[u];e;e=E[e].next) 92 { 93 int v=E[e].to; 94 if(v==F) 95 continue; 96 dfs3(v,u); 97 for(int i=0;i<=m;++i) 98 for(int j=0;j<=i;++j) 99 { 100 ans=(ans+C[m][i]*C[i][j]%mod*tmp[m-i]%mod*f[u][j]%mod*g[v][i-j]%mod)%mod; 101 ans=(ans+C[m][i]*C[i][j]%mod*tmp[m-i]%mod*g[u][j]%mod*f[v][i-j]%mod)%mod; 102 } 103 for(int i=0;i<=m;++i) 104 f[u][i]=(f[u][i]+f[v][i])%mod,g[u][i]=(g[u][i]+g[v][i])%mod; 105 } 106 } 107 int main() 108 { 109 // freopen("dream6.in","r",stdin); 110 ios::sync_with_stdio(false); 111 cin>>n>>m; 112 init(); 113 for(int i=2;i<=n;++i) 114 { 115 int x,y; 116 cin>>x>>y; 117 add(x,y); 118 add(y,x); 119 } 120 dfs1(1,0); 121 dfs2(1,0,-up[1],0,0); 122 dfs3(1,0); 123 cout<<(ans%mod+mod)%mod<<endl; 124 return 0; 125 }
2020_10_07:
A.对于一个权值,记录所有可能到达的位置。bitset优化。但我却手写了一个bitset(因为用了错误的复杂度)。

1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,d; 4 const int LEN=32768; 5 int OUT,tmp[LEN]; 6 struct Bitset 7 { 8 unsigned a[LEN]; 9 void reset(){memset(a,0,sizeof(unsigned)*min(OUT,LEN));} 10 Bitset(){reset();} 11 void set(int x){a[x>>5]|=1<<(x&31);} 12 void reset(int x){a[x>>5]&=~(1<<(x&31));} 13 void operator |=(Bitset &b) 14 { 15 int up=min(LEN,OUT); 16 for(int i=0;i<up;i++)a[i]=a[i]|b.a[i]; 17 } 18 void operator <<=(const int t) 19 { 20 unsigned last=0; 21 int high=t>>5,low=t&31; 22 int up=min(LEN,OUT); 23 for(int i=0;i<up;++i) 24 tmp[i]=0; 25 if(low) 26 for(int i=0;i+high<up;i++) 27 { 28 tmp[i+high]=last|(a[i]<<low); 29 last=a[i]>>(32-low); 30 } 31 else 32 for(int i=0;i+high<up;i++) 33 tmp[i+high]=last|(a[i]<<low); 34 for(int i=0;i<up;++i) 35 a[i]=tmp[i]; 36 } 37 inline int count() 38 { 39 int s=0; 40 for(int i=0;i<LEN;++i) 41 s+=__builtin_popcount(a[i]); 42 return s; 43 } 44 }; 45 Bitset have[95],g[95],ans; 46 int size,head[95]; 47 struct edge 48 { 49 int to,next,w; 50 }E[55555]; 51 inline void add(int u,int v,int w) 52 { 53 E[++size].to=v; 54 E[size].next=head[u]; 55 E[size].w=w; 56 head[u]=size; 57 } 58 inline void get(int bias) 59 { 60 if(bias==0) 61 { 62 for(int u=1;u<=n;++u) 63 for(int i=head[u];i;i=E[i].next) 64 { 65 int v=E[i].to,w=E[i].w; 66 if(v==1) 67 have[u].set(w); 68 } 69 return; 70 } 71 OUT=2*bias; 72 // cout<<"? "<<OUT<<endl; 73 for(int u=1;u<=n;++u) 74 { 75 g[u].reset(); 76 for(int i=head[u];i;i=E[i].next) 77 { 78 int v=E[i].to,w=E[i].w; 79 if(!w) 80 g[u]|=have[v]; 81 } 82 g[u]<<=bias; 83 for(int i=head[u];i;i=E[i].next) 84 { 85 int v=E[i].to,w=E[i].w; 86 if(w) 87 g[u]|=have[v]; 88 } 89 } 90 for(int u=1;u<=n;++u) 91 have[u]=g[u]; 92 } 93 int main() 94 { 95 // freopen("a.in","r",stdin); 96 ios::sync_with_stdio(false); 97 cin>>n>>m>>d; 98 // n=90,m=90*89,d=20; 99 for(int i=1;i<=m;++i) 100 { 101 int x,y,z; 102 cin>>x>>y>>z; 103 add(x,y,z); 104 add(y,x,z); 105 } 106 /* 107 for(int i=1;i<=n;++i) 108 for(int j=i+1;j<=n;++j) 109 { 110 int x=i,y=j,z=rand()%2; 111 add(x,y,z); 112 add(y,x,z); 113 add(x,y,z); 114 add(y,x,z); 115 } 116 */ 117 get(0); 118 for(int i=1;i<d;++i) 119 get(1<<i); 120 OUT=LEN; 121 for(int i=1;i<=n;++i) 122 ans|=have[i]; 123 cout<<ans.count()<<endl; 124 return 0; 125 }
B.
不妨反过来考虑(同时,你的私家车显然不能停在其他人的车上,但数据竟然有这种情况!)。答案首先是单调增的,如果答案会改变,那么这个正方形一定会包含刚刚消去的位置。显然用单调队列判断即可。

1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=2005; 4 int n,m,k,ans[maxn]; 5 int U[maxn][maxn],D[maxn][maxn],L[maxn][maxn],f[maxn][maxn]; 6 int a[maxn][maxn]; 7 struct pt 8 { 9 int x,y; 10 }b[maxn]; 11 inline void init() 12 { 13 for(int i=1;i<=n;++i) 14 for(int j=1;j<=m;++j) 15 if(!a[i][j]) 16 { 17 L[i][j]=L[i][j-1]+1; 18 U[i][j]=U[i-1][j]+1; 19 f[i][j]=min(min(L[i][j],U[i][j]),f[i-1][j-1]+1); 20 ans[k]=max(ans[k],f[i][j]); 21 } 22 for(int j=1;j<=m;++j) 23 for(int i=n;i>=1;--i) 24 D[i][j]=a[i][j]?0:D[i+1][j]+1; 25 } 26 inline void clear(int x,int y) 27 { 28 --a[x][y]; 29 for(int i=1;i<=n;++i) 30 U[i][y]=a[i][y]?0:U[i-1][y]+1; 31 for(int i=n;i>=1;--i) 32 D[i][y]=a[i][y]?0:D[i+1][y]+1; 33 } 34 int q[maxn],tmp1[maxn],tmp2[maxn]; 35 inline bool ok(int len,int x,int y) 36 { 37 if(len>n||len>m) 38 return false; 39 int l=max(1,y-len+1),r=min(m,y+len-1); 40 int tot1=0,tot2=0,head=1,tail=0; 41 for(int i=l;i<=r;++i) 42 { 43 while(head<=tail&&i-q[head]==len) 44 ++head; 45 while(head<=tail&&U[x][i]<=U[x][q[tail]]) 46 --tail; 47 q[++tail]=i; 48 if(i-l+1>=len) 49 tmp1[++tot1]=U[x][q[head]]; 50 } 51 head=1,tail=0; 52 for(int i=l;i<=r;++i) 53 { 54 while(head<=tail&&i-q[head]==len) 55 ++head; 56 while(head<=tail&&D[x][i]<=D[x][q[tail]]) 57 --tail; 58 q[++tail]=i; 59 if(i-l+1>=len) 60 tmp2[++tot2]=D[x][q[head]]; 61 } 62 // cout<<"H "<<tot1<<endl; 63 // for(int i=1;i<=tot1;++i) 64 // cout<<tmp1[i]<<" "<<tmp2[i]<<endl; 65 for(int i=1;i<=tot1;++i) 66 if(tmp1[i]+tmp2[i]-1>=len) 67 return true; 68 return false; 69 } 70 int main() 71 { 72 // freopen("a.in","r",stdin); 73 ios::sync_with_stdio(false); 74 cin>>n>>m>>k; 75 for(int i=1;i<=n;++i) 76 { 77 string str; 78 cin>>str; 79 for(int j=1;j<=m;++j) 80 if(str[j-1]=='X') 81 a[i][j]=1; 82 } 83 for(int i=1;i<=k;++i) 84 { 85 cin>>b[i].x>>b[i].y; 86 ++a[b[i].x][b[i].y]; 87 } 88 init(); 89 int pos=ans[k]; 90 for(int i=k;i>1;--i) 91 { 92 clear(b[i].x,b[i].y); 93 while(ok(pos+1,b[i].x,b[i].y)) 94 ++pos; 95 ans[i-1]=pos; 96 } 97 for(int i=1;i<=k;++i) 98 cout<<ans[i]<<' '; 99 return 0; 100 }
C.
$mu_n^2=sum_{d^2|n}{mu_d}$

1 #include<bits/stdc++.h> 2 #define mod 1000000007 3 using namespace std; 4 typedef long long int ll; 5 const int maxn=1E6+5; 6 const int limit=1000000; 7 int size,prime[maxn],have[maxn],mu[maxn]; 8 bool vis[maxn]; 9 ll n; 10 inline void init() 11 { 12 for(int i=2;i<=limit;++i) 13 { 14 if(!vis[i]) 15 prime[++size]=i,have[i]=1,mu[i]=-1; 16 for(int j=1;j<=size&&prime[j]*i<=limit;++j) 17 { 18 int num=prime[j]*i; 19 vis[num]=1; 20 have[num]=have[i]; 21 if(i%prime[j]==0) 22 break; 23 ++have[num]; 24 mu[num]=-mu[i]; 25 } 26 } 27 mu[1]=1; 28 } 29 inline ll f(int x) 30 { 31 return have[x]; 32 } 33 inline void solve() 34 { 35 ll s=0,up=sqrt(n); 36 for(int k=1;k<=up;++k) 37 { 38 if(!mu[k]) 39 continue; 40 ll g=0,d=n/k/k; 41 ll sd=sqrt(d); 42 for(int l=1;l<=sd;++l) 43 g=(g+d/l)%mod; 44 g=(g*2-sd*sd%mod+mod)%mod*mu[k]%mod; 45 s=(s+g)%mod; 46 } 47 cout<<(s%mod+mod)%mod<<endl; 48 } 49 int main() 50 { 51 ios::sync_with_stdio(false); 52 init(); 53 cin>>n; 54 solve(); 55 return 0; 56 }
2020_10_08:
A.CF717F

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 const int maxn=1005; 5 int n,m; 6 ll a[maxn],f[maxn][maxn],tmp[maxn]; 7 inline void solve() 8 { 9 ll q; 10 cin>>q; 11 int pos=upper_bound(tmp,tmp+n+1,q)-tmp; 12 cout<<n-pos+1<<endl; 13 } 14 int main() 15 { 16 ios::sync_with_stdio(false); 17 cin>>n>>m; 18 for(int i=1;i<=n;++i) 19 cin>>a[i]; 20 reverse(a+1,a+n+1); 21 for(int i=1;i<=n;++i) 22 { 23 for(int j=1;j<=i;++j) 24 f[i][j]=min(max(f[i-1][j]-a[i],(ll)0),f[i-1][j-1]); 25 //it will be impossible if the initial value is minus !!! 26 f[i][0]=max(f[i-1][0]-a[i],(ll)0); 27 } 28 for(int i=0;i<=n;++i) 29 tmp[i]=f[n][n-i]; 30 while(m--) 31 solve(); 32 return 0; 33 }
B.
1.用线性gcd。
2.没有平方因子的性质:设f(n,m)为$sum_{i=1}^{m}{phi(i*n)}$,若p|n(n没有平方因子),那么f(n,m)=(p-1)*f(n/p,m)+f(n,m/p)。把它拆成有p因子的贡献和没有p因子的贡献,然后推式子(但我不能感性理解)。
3.单测,线筛啊。
4.数据太水了,gcd的log过去了。

1 #include<bits/stdc++.h> 2 #define MOD 1000000007 3 using namespace std; 4 typedef long long int ll; 5 const int maxn=1E7+5; 6 const int limit=10000000; 7 int size,prime[maxn],phi[maxn],sum[maxn]; 8 int tot,tmp[555]; 9 bool vis[maxn]; 10 //IMPLAUSIABLE TO MERGE THESE TWO QUIZ !!! 11 inline ll qpow(ll x,ll y,ll mod) 12 { 13 ll ans=1,base=x; 14 while(y) 15 { 16 if(y&1) 17 ans=ans*base%mod; 18 base=base*base%mod; 19 y>>=1; 20 } 21 return ans%mod; 22 } 23 inline void init() 24 { 25 for(int i=2;i<=limit;++i) 26 { 27 if(!vis[i]) 28 prime[++size]=i,phi[i]=i-1; 29 for(int j=1;j<=size&&prime[j]*i<=limit;++j) 30 { 31 int num=prime[j]*i; 32 vis[num]=1; 33 if(i%prime[j]==0) 34 { 35 phi[num]=phi[i]*prime[j]; 36 break; 37 } 38 phi[num]=phi[i]*(prime[j]-1); 39 } 40 } 41 phi[1]=1; 42 for(int i=1;i<=limit;++i) 43 sum[i]=(sum[i-1]+phi[i])%MOD; 44 } 45 ll fuckyou(ll k,ll mod) 46 { 47 if(mod==1) 48 return 0; 49 ll x=fuckyou(k,phi[mod]); 50 return qpow(k,x+phi[mod],mod); 51 } 52 map<int,map<int,ll> >G; 53 ll get(int n,int m) 54 { 55 if(G[n][m]) 56 return G[n][m]; 57 if(m==0) 58 return 0; 59 if(n==1) 60 return sum[m]; 61 if(m==1) 62 return phi[n]; 63 for(int i=1;i<=tot;++i) 64 { 65 int x=tmp[i]; 66 if(n%x==0) 67 return G[n][m]=(get(n/x,m)*phi[x]%MOD+get(n,m/x))%MOD; 68 } 69 assert(0); 70 return 0; 71 } 72 int main() 73 { 74 ios::sync_with_stdio(false); 75 init(); 76 ll n,m,p; 77 cin>>n>>m>>p; 78 ll g=n; 79 for(int i=2;i<=n;++i) 80 if(n%i==0) 81 { 82 tmp[++tot]=i; 83 n/=i; 84 } 85 if(n>=2) 86 tmp[++tot]=n; 87 cout<<fuckyou(get(g,m),p)<<endl; 88 return 0; 89 }
C.51nod1355

1 #include<bits/stdc++.h> 2 #define mod 1000000007 3 using namespace std; 4 typedef long long int ll; 5 ll n,f[1000005],g[1000005],ans=1; 6 bool vis[1000005]; 7 inline ll qpow(ll x,ll y) 8 { 9 ll ans=1,base=x; 10 while(y) 11 { 12 if(y&1) 13 ans=ans*base%mod; 14 base=base*base%mod; 15 y>>=1; 16 } 17 return ans; 18 } 19 void init() 20 { 21 g[1]=f[1]=1; 22 for(int i=2;i<=1000000;++i) 23 g[i]=f[i]=(f[i-1]+f[i-2])%mod; 24 for(int i=2;i<=1000000;++i) 25 { 26 ll x=qpow(g[i],mod-2); 27 for(int j=2;j*i<=1000000;++j) 28 g[j*i]=g[j*i]*x%mod; 29 } 30 } 31 int main() 32 { 33 ios::sync_with_stdio(false); 34 init(); 35 cin>>n; 36 for(int i=1;i<=n;++i) 37 { 38 int x; 39 cin>>x; 40 vis[x]=1; 41 } 42 for(int i=1;i<=1000000;++i) 43 for(int j=1;j*i<=1000000;++j) 44 if(vis[j*i]) 45 { 46 ans=ans*g[i]%mod; 47 break; 48 } 49 cout<<ans<<endl; 50 return 0; 51 }