1. 程式人生 > 其它 >7.7洛谷多校3補

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特判。

質因數分解我用的是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 }