7.7洛谷多校3补
A
一个DAG,当一个点作为控制点时,它可以控制所有它指向的点。有边直接相连的点不能都为控制点,每个点要么被控制要么是控制点,求最少的控制点数量。
n<=10^5 m<=10^6
题解:
入度为0的点必定为控制点。
直接拓扑排序,控制点和它所控制的点直接删除,再让新的入度为0的点成为控制点即可。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 int tot=0,ne[N*10],t[N*10],he[N],d[N],q[N],py[N]; 5 void link(int x,int y) 6 { 7 tot++; 8 ne[tot]=he[x]; 9 he[x]=tot; 10 t[tot]=y; 11 } 12 int main() 13 { 14 int n,m; 15 scanf("%d%d",&n,&m); 16 for (int i=1;i<=m;i++) 17 { 18 int x,y; 19 scanf("%d%d",&x,&y); 20 link(x,y); 21 d[y]++; 22 } 23 int k=0; 24 for (int i=1;i<=n;i++) if (!d[i]) q[++k]=i; 25 int i=0,ans=0; 26 while (i<k) 27 { 28 i++; 29 int x=q[i],fl=0; 30 if (!py[x]) ans++,fl=1; 31 for (int j=he[x];j;j=ne[j]) 32 { 33 py[t[j]]=py[t[j]]+fl; 34 d[t[j]]--; 35 if (d[t[j]]==0) q[++k]=t[j]; 36 } 37 } 38 printf("%d\n",ans); 39 }
B
给定n个数a[1]到a[n]和x,设μ(x)为x的莫比乌斯函数,给出m个询问形如(l,r),求i(从l到r)∏(μ(a[i])+a[i]+x) %998244353
LCM(a[i])<=10^15 a[i]<=10^15 n,m<=3*10^5
题解:
LCM(a[i])是一个很有用的性质,说明所有a[i]的不同的质数因子只有十几个。
所以求出所有质数因子,然后对每个数暴力分解求莫比乌斯函数即可,答案的话可以用类似前缀积的东西处理,但不能是前缀积,遇到0特判。
质因数分解我用的是pollared rho,标程给的做法是直接暴力...很难认同。
pollared rho不会做很多次,每次找到一个非1的数分解找到其质因数,然后让所有的数试除这些质因数,并去掉试除部分,这样就可以保证每个质数因子不会被重复找。
代码:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <stdio.h> 5 #include <algorithm> 6 #include <math.h> 7 #include <stdlib.h> 8 9 #include<time.h> 10 #define ll long long 11 12 #define INF 0x3f3f3f3f 13 #define maxn 10000+10 14 #define cle(a) memset(a,0,sizeof(a)) 15 const double eps=1e-5; 16 const int mo=998244353; 17 using namespace std; 18 19 const int S=5;//随机算法判定次数,S越大,判错概率越小 20 //计算 (a*b)%c. a,b都是long long的数,直接相乘可能溢出的 21 // a,b,c <2^63 22 ll mult_mod(ll a,ll b,ll c) 23 { 24 a%=c; 25 b%=c; 26 ll ret=0; 27 while(b) 28 { 29 if(b&1){ret+=a;ret%=c;} 30 a<<=1; 31 if(a>=c)a%=c; 32 b>>=1; 33 } 34 return ret; 35 } 36 ll pow_mod(ll x,ll n,ll mod) 37 { 38 if(n==1)return x%mod; 39 x%=mod; 40 ll tmp=x; 41 ll ret=1; 42 while(n) 43 { 44 if(n&1) ret=mult_mod(ret,tmp,mod); 45 tmp=mult_mod(tmp,tmp,mod); 46 n>>=1; 47 } 48 return ret; 49 } 50 //以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数 51 //一定是合数返回true,不一定返回false 52 bool check(ll a,ll n,ll x,ll t) 53 { 54 ll ret=pow_mod(a,x,n); 55 ll last=ret; 56 for(int i=1;i<=t;i++) 57 { 58 ret=mult_mod(ret,ret,n); 59 if(ret==1&&last!=1&&last!=n-1) return true;//合数 60 last=ret; 61 } 62 if(ret!=1) return true; 63 return false; 64 } 65 // Miller_Rabin()算法素数判定 66 //是素数返回true.(可能是伪素数,但概率极小) 67 //合数返回false; 68 bool Miller_Rabin(ll n) 69 { 70 if(n<2)return false; 71 if(n==2)return true; 72 if((n&1)==0) return false;//偶数 73 ll x=n-1; 74 ll t=0; 75 while((x&1)==0){x>>=1;t++;} 76 for(int i=0;i<S;i++) 77 { 78 ll a=rand()%(n-1)+1;//rand()需要stdlib.h头文件 79 if(check(a,n,x,t)) 80 return false;//合数 81 } 82 return true; 83 } 84 ll factor[100];//质因数分解结果(刚返回时是无序的) 85 int tol;//质因数的个数。数组小标从0开始 86 ll gcd(ll a,ll b) 87 { 88 if(a==0)return 1;//??????? 89 if(a<0) return gcd(-a,b); 90 while(b) 91 { 92 ll t=a%b; 93 a=b; 94 b=t; 95 } 96 return a; 97 } 98 ll Pollard_rho(ll x,ll c) 99 { 100 ll i=1,k=2; 101 ll x0=rand()%x; 102 ll y=x0; 103 while(1) 104 { 105 i++; 106 x0=(mult_mod(x0,x0,x)+c)%x; 107 ll d=gcd(y-x0,x); 108 if(d!=1&&d!=x) return d; 109 if(y==x0) return x; 110 if(i==k){y=x0;k+=k;} 111 } 112 } 113 //对n进行素因子分解 114 void findfac(ll n) 115 { 116 if(Miller_Rabin(n))//素数 117 { 118 factor[tol++]=n; 119 return; 120 } 121 ll p=n; 122 while(p>=n)p=Pollard_rho(p,rand()%(n-1)+1); 123 findfac(p); 124 findfac(n/p); 125 } 126 long long ksm(long long x,long long y) 127 { 128 long long ret=1; 129 while (y) 130 { 131 if (y&1) ret=ret*x%mo; 132 x=x*x%mo; 133 y=y>>1; 134 } 135 return ret; 136 } 137 long long a[500050],b[500050],c[500050],mu[500050],s[500050]; 138 int main() 139 { 140 //freopen("test.in","r",stdin); 141 int n,m,x; 142 scanf("%d%d%d",&n,&m,&x); 143 for (int i=1;i<=n;i++) scanf("%lld",&a[i]),b[i]=a[i]; 144 int kk=0; 145 for (int i=1;i<=n;i++) 146 { 147 if (b[i]!=1) 148 { 149 tol=0; 150 findfac(b[i]); 151 for (int j=0;j<tol;j++) 152 { 153 c[++kk]=factor[j]; 154 for (int k=1;k<=n;k++) while (b[k]%factor[j]==0) b[k]=b[k]/factor[j]; 155 } 156 } 157 } 158 for (int i=1;i<=n;i++) 159 { 160 b[i]=a[i]; 161 mu[i]=1; 162 for (int j=1;j<=kk;j++) 163 { 164 165 if (b[i]%c[j]==0) 166 { 167 int tmp=0; 168 while (b[i]%c[j]==0) 169 { 170 tmp++; 171 b[i]=b[i]/c[j]; 172 } 173 if (tmp>=2) 174 { 175 mu[i]=0; 176 break; 177 } 178 else mu[i]=-mu[i]; 179 } 180 } 181 } 182 a[0]=1; 183 for (int i=1;i<=n;i++) 184 { 185 a[i]=(a[i]+mu[i]+x)%mo; 186 if (a[i]==0) s[i]=1,a[i]=1; 187 s[i]=s[i]+s[i-1]; 188 a[i]=a[i]*a[i-1]%mo; 189 } 190 for (int i=1;i<=m;i++) 191 { 192 int l,r; 193 scanf("%d%d",&l,&r); 194 if (s[r]-s[l-1]) printf("0\n"); 195 else printf("%lld\n",a[r]*ksm(a[l-1],mo-2)%mo); 196 } 197 /*ll n; 198 while(cin>>n){ 199 tol=0; 200 findfac(n); 201 for(int i=0;i<tol;i++)cout<<factor[i]<<endl; 202 //质因子 203 }*/ 204 return 0; 205 }

浙公网安备 33010602011771号