A.求矩阵的秩。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 int n,m; 5 ll a[205][205],b[205][205]; 6 inline ll qpow(ll x,ll y,ll mod) 7 { 8 ll ans=1,base=x; 9 while(y) 10 { 11 if(y&1) 12 ans=ans*base%mod; 13 base=base*base%mod; 14 y>>=1; 15 } 16 return ans; 17 } 18 inline void add(ll&x,ll y,ll mod)//!!!!!!!!!!!!!! 19 { 20 x=(x+y)%mod; 21 } 22 inline int test(ll mod) 23 { 24 for(int i=1;i<=n;++i) 25 for(int j=1;j<=m;++j) 26 b[i][j]=a[i][j]; 27 for(int i=1;i<=m;++i) 28 { 29 bool ok=0; 30 for(int j=i;j<=n;++j) 31 if(b[j][i]) 32 { 33 swap(b[i],b[j]); 34 ok=1; 35 break; 36 } 37 if(!ok) 38 return i-1; 39 ll s=qpow(b[i][i],mod-2,mod); 40 for(int j=i+1;j<=n;++j) 41 { 42 ll g=(mod-b[j][i]*s%mod)%mod; 43 for(int k=i;k<=m;++k) 44 add(b[j][k],b[i][k]*g,mod); 45 } 46 } 47 return m; 48 } 49 int main() 50 { 51 // freopen("kangaroo.in","r",stdin); 52 // freopen("kangaroo.out","w",stdout); 53 ios::sync_with_stdio(false); 54 cin>>n>>m; 55 for(int i=1;i<=n;++i) 56 for(int j=1;j<=m;++j) 57 cin>>a[i][j]; 58 if(n<m) 59 { 60 for(int i=1;i<=n;++i) 61 for(int j=i;j<=m;++j) 62 swap(a[i][j],a[j][i]); 63 swap(n,m); 64 } 65 cout<<max(max(max(test(998244353),test(1000000007)),test(19260817)),test(1145141))<<endl; 66 return 0; 67 }
B.给出一个树,树上节点u能到达后代节点v当且仅当a[u]是a[v]的倍数,求1到所有节点的路径数。数字的约数个数不超过100000。
考虑如下两种方法:
1.dfs时,每次到达一个节点时用O(1)从bucket中获得答案,然后花O(d)时间更新bucket(找到所有约数)。
2.dfs时,每次到达一个节点时用O(d)时间访问bucket中的所有可能的倍数,然后O(1)更新数组。
为了降低复杂度,我们可以将一个数字分为两部分:前半部分用来更新数组,使用算法1;后半部分用来统计答案,使用算法2。
这就是csp初赛的最后一题。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define mod 1000000007 3 using namespace std; 4 typedef long long int ll; 5 typedef long double ld; 6 const int maxn=1E5+5; 7 int n,size,head[maxn]; 8 ll a[maxn],ans[maxn]; 9 int totP,limit,buf[21],up[21],b[maxn][21]; 10 struct edge 11 { 12 int to,next; 13 }E[maxn*2]; 14 inline ll read() 15 { 16 char ch=getchar(); 17 while(!isdigit(ch))ch=getchar(); 18 ll s=ch-'0';ch=getchar(); 19 while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} 20 return s; 21 } 22 int G[55]; 23 inline void write(ll x) 24 { 25 int g=0; 26 do{G[++g]=x%10;x/=10;}while(x); 27 for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n'); 28 } 29 inline void add(int u,int v) 30 { 31 E[++size].to=v; 32 E[size].next=head[u]; 33 head[u]=size; 34 } 35 int tmp[21]; 36 ll bucket[10000005]; 37 int pre[maxn]; 38 ll getAns(int u,int s,int now) 39 { 40 if(s>limit) 41 { 42 if(!pre[u]) 43 while(s<totP) 44 { 45 pre[u]+=b[u][s]*buf[s]; 46 ++s; 47 } 48 now+=pre[u]; 49 return bucket[now]; 50 } 51 ll sum=0; 52 now+=buf[s]*b[u][s]; 53 for(int i=b[u][s];i<=up[s];++i,now+=buf[s]) 54 sum+=getAns(u,s+1,now); 55 return sum; 56 } 57 void addAns(int u,int s,int now,ll x,bool flag) 58 { 59 if(s==totP) 60 { 61 if(flag) 62 { 63 bucket[now]+=x; 64 if(bucket[now]>=mod) 65 bucket[now]-=mod; 66 } 67 else 68 { 69 bucket[now]-=x; 70 if(bucket[now]<0) 71 bucket[now]+=mod; 72 } 73 return; 74 } 75 if(s<=limit) 76 { 77 while(s<=limit) 78 { 79 now+=b[u][s]*buf[s]; 80 ++s; 81 } 82 addAns(u,s,now,x,flag); 83 } 84 else 85 for(int i=0;i<=b[u][s];++i,now+=buf[s]) 86 addAns(u,s+1,now,x,flag); 87 } 88 void dfs(int u,int F) 89 { 90 if(u==1) 91 ans[u]=1; 92 else 93 ans[u]=getAns(u,0,0)%mod; 94 addAns(u,0,0,ans[u],1); 95 for(int i=head[u];i;i=E[i].next) 96 { 97 int v=E[i].to; 98 if(v==F) 99 continue; 100 dfs(v,u); 101 } 102 addAns(u,0,0,ans[u],0); 103 } 104 namespace MATH 105 { 106 const int len=10; 107 const int test[len]={2,3,5,7,11,13,17,19,23,29}; 108 inline ll mul(ll x,ll y,ll M) 109 { 110 return (ll(x*y-(ll((ld)x*y/M))*M)%M+M)%M; 111 } 112 inline ll qpow(ll x,ll y,ll M) 113 { 114 ll ans=1,base=x; 115 while(y) 116 { 117 if(y&1) 118 ans=mul(ans,base,M); 119 base=mul(base,base,M); 120 y>>=1; 121 } 122 return ans; 123 } 124 inline bool miller(ll x) 125 { 126 for(int i=0;i<len;++i) 127 { 128 if(x<test[i]) 129 return false; 130 else if(x==test[i]) 131 return true; 132 ll now=qpow(test[i],x-1,x),g=x-1; 133 if(now!=1) 134 return false; 135 while(now==1&&!(g&1)) 136 { 137 g>>=1; 138 now=qpow(test[i],g,x); 139 if(now!=1&&now!=x-1) 140 return false; 141 } 142 } 143 return true; 144 } 145 ll gcd(ll x,ll y) 146 { 147 return x%y==0?y:gcd(y,x%y); 148 } 149 inline ll f(ll x,ll y,ll M) 150 { 151 return (mul(x,x,M)+y)%M; 152 } 153 inline ll get(ll n,ll c,int steps) 154 { 155 if(!(n&1)) 156 return 2; 157 ll x=2,y=2,d=1; 158 while(true) 159 { 160 ll tmpx=x,tmpy=y; 161 for(int i=1;i<=steps;++i) 162 { 163 x=f(x,c,n); 164 y=f(y,c,n); 165 y=f(y,c,n); 166 d=mul(d,((y-x)%n+n)%n,n); 167 } 168 d=gcd(d,n); 169 if(d==1) 170 continue; 171 if(d!=n) 172 return d; 173 x=tmpx,y=tmpy; 174 for(int i=1;i<=steps;++i) 175 { 176 x=f(x,c,n); 177 y=f(y,c,n); 178 y=f(y,c,n); 179 d=gcd(((y-x)%n+n)%n,n); 180 if(d!=1&&d!=n) 181 return d; 182 } 183 return 0; 184 } 185 } 186 vector<ll>wait; 187 void pollard(ll n) 188 { 189 if(miller(n)) 190 { 191 wait.push_back(n); 192 return; 193 } 194 ll now=0,c=1,g=pow(n,0.1)+1; 195 while(!now) 196 now=get(n,++c,g); 197 pollard(now),pollard(n/now); 198 } 199 int prime[555]; 200 void main() 201 { 202 if(a[1]!=1) 203 pollard(a[1]); 204 sort(wait.begin(),wait.end()); 205 int last=-1; 206 for(int i=0;i<wait.size();++i) 207 { 208 if(wait[i]!=last) 209 { 210 ++up[totP]; 211 prime[totP++]=wait[i]; 212 } 213 else 214 ++up[totP-1]; 215 last=wait[i]; 216 } 217 buf[totP-1]=1; 218 for(int i=totP-2;i>=0;--i) 219 buf[i]=buf[i+1]*(up[i+1]+1); 220 int s=up[0]+1,now=buf[0]; 221 limit=0; 222 for(int i=1;i<totP;++i) 223 { 224 if(max(s,buf[0]/s)<now) 225 { 226 now=max(s,buf[0]/s); 227 limit=i; 228 } 229 s*=up[i]+1; 230 } 231 for(int u=1;u<=n;++u) 232 { 233 ll x=a[u]; 234 for(int i=0;i<totP;++i) 235 while(x%prime[i]==0) 236 { 237 x/=prime[i]; 238 ++b[u][i]; 239 } 240 } 241 /* 242 cout<<"PRIME : "; 243 for(int i=0;i<totP;++i) 244 cout<<prime[i]<<" ";cout<<endl; 245 for(int u=1;u<=n;++u) 246 { 247 cout<<u<<" : "; 248 for(int i=0;i<totP;++i) 249 cout<<b[u][i]<<" ";cout<<endl; 250 } 251 cout<<"LIMIT : "<<limit<<endl; 252 */ 253 } 254 } 255 inline void init() 256 { 257 MATH::main(); 258 } 259 inline void solve() 260 { 261 init(); 262 dfs(1,0); 263 for(int i=1;i<=n;++i) 264 write((ans[i]%mod+mod)%mod); 265 } 266 int main() 267 { 268 freopen("walk.in","r",stdin); 269 freopen("walk.out","w",stdout); 270 ios::sync_with_stdio(false); 271 n=read(); 272 for(int i=2;i<=n;++i) 273 { 274 int x=read(),y=read(); 275 add(x,y); 276 add(y,x); 277 } 278 for(int i=1;i<=n;++i) 279 a[i]=read(); 280 solve(); 281 return 0; 282 }
C.三元环计数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned long long ull; 4 const int maxn=2E5+5; 5 int n,m; 6 int size,head[maxn]; 7 int size2,head2[maxn],deg[maxn]; 8 ull A,B,C,ans,a[maxn],sum[maxn]; 9 inline int read() 10 { 11 char ch=getchar(); 12 while(!isdigit(ch))ch=getchar(); 13 int s=ch-'0';ch=getchar(); 14 while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} 15 return s; 16 } 17 struct edge 18 { 19 int to,next; 20 }E[maxn*2],E2[maxn*2]; 21 inline void add(int u,int v) 22 { 23 E[++size].to=v; 24 E[size].next=head[u]; 25 head[u]=size; 26 } 27 inline void add2(int u,int v) 28 { 29 E2[++size2].to=v; 30 E2[size2].next=head2[u]; 31 head2[u]=size2; 32 } 33 inline ull C2(int x) 34 { 35 return (ull)x*(x-1)/2; 36 } 37 inline void get0() 38 { 39 for(int i=0;i<n;++i) 40 { 41 ans+=A*i*C2(n-i-1); 42 ans+=B*i*i*(n-i-1); 43 ans+=C*i*C2(i); 44 } 45 } 46 inline void get1() 47 { 48 for(int u=0;u<n;++u) 49 for(int e=head[u];e;e=E[e].next) 50 { 51 int v=E[e].to; 52 if(u>v) 53 continue; 54 int x=u,y=v; 55 ans-=(ull)(n-y-1)*(A*x+B*y)+C*(sum[n-1]-sum[y]); 56 ans-=(ull)(y-x-1)*(A*x+C*y)+B*(sum[y-1]-sum[x]); 57 if(x) 58 ans-=(ull)(x)*(B*x+C*y)+A*(sum[x-1]); 59 } 60 } 61 int tmpL[maxn],tmpR[maxn]; 62 inline void get2() 63 { 64 for(int u=0;u<n;++u) 65 { 66 int totL=0,totR=0; 67 ull sumL=0,sumR=0; 68 for(int e=head[u];e;e=E[e].next) 69 { 70 int v=E[e].to; 71 if(v<u) 72 tmpL[++totL]=v; 73 else 74 tmpR[++totR]=v; 75 } 76 ans+=B*u*totL*totR; 77 78 sort(tmpL+1,tmpL+totL+1); 79 sort(tmpR+1,tmpR+totR+1); 80 81 for(int i=1;i<=totL;++i) 82 { 83 ans+=A*tmpL[i]*totR; 84 ans+=A*tmpL[i]*(totL-i); 85 ans+=B*tmpL[i]*(i-1); 86 } 87 ans+=C*u*C2(totL); 88 89 for(int i=1;i<=totR;++i) 90 { 91 ans+=C*tmpR[i]*totL; 92 ans+=B*tmpR[i]*(totR-i); 93 ans+=C*tmpR[i]*(i-1); 94 } 95 ans+=A*u*C2(totR); 96 } 97 } 98 int TI,color[maxn]; 99 inline void get3() 100 { 101 for(int u=0;u<n;++u) 102 for(int i=head[u];i;i=E[i].next) 103 { 104 int v=E[i].to; 105 if(deg[u]==deg[v]&&u>v) 106 add2(u,v); 107 else if(deg[u]>deg[v]) 108 add2(u,v); 109 } 110 for(int u=0;u<n;++u) 111 { 112 ++TI; 113 for(int i=head2[u];i;i=E2[i].next) 114 color[E2[i].to]=TI; 115 for(int i=head2[u];i;i=E2[i].next) 116 { 117 int v=E2[i].to; 118 for(int j=head2[v];j;j=E2[j].next) 119 { 120 int w=E2[j].to; 121 if(color[w]==TI) 122 { 123 int x=min(min(u,v),w); 124 int y=max(max(u,v),w); 125 int z=u; 126 if(x!=u&&y!=u) 127 z=u; 128 else if(x!=v&&y!=v) 129 z=v; 130 else 131 z=w; 132 ans-=A*x+B*z+C*y; 133 } 134 } 135 } 136 } 137 } 138 int main() 139 { 140 freopen("girls.in","r",stdin); 141 freopen("girls.in","r",stdin); 142 ios::sync_with_stdio(false); 143 n=read(),m=read(),A=read(),B=read(),C=read(); 144 for(int i=1;i<=m;++i) 145 { 146 int x=read(),y=read(); 147 add(x,y); 148 add(y,x); 149 ++deg[x],++deg[y]; 150 } 151 for(int i=1;i<n;++i) 152 sum[i]=sum[i-1]+i; 153 get0(); 154 get1(); 155 get2(); 156 get3(); 157 cout<<ans<<endl; 158 return 0; 159 }