7.7洛谷多校3補
阿新 • • 發佈:2021-07-10
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(intx,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特判。
質因數分解我用的是pollaredrho,標程給的做法是直接暴力...很難認同。
pollaredrho不會做很多次,每次找到一個非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 }