ProblemJ.prime game(質因數分解)
阿新 • • 發佈:2020-11-24
題目連結:https://codeforces.com/gym/101981
題意:給你n個數,讓你求[1,n]所有區間的不同質因數個數;
解法:利用試除法分解合數,再分解過程中能求出區間[1,n]中一共有多少個不同素因數,我們假設從[1,n]的所有區間都存在全部不同素因數,等差數列求出區間數,再減去每一個質因數絕對不存在的每個區間;
程式碼如下:
/************************************************************************* > File Name: problemA.cpp # Author: Badwoman # mail: [email protected] > Created Time: 2020年11月22日 星期日 13時01分44秒 ************************************************************************/ #include<set> #include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<cstdlib> #include<map> #include<algorithm> #include<vector> #include<queue> #include<stack> #define ll long long #define ull unsigned long long #define pb push_back #define mp make_pair using namespace std; ll n,k; const ll N = 1e6+10; bool st[N];ll prime[N],tot,arr[N]; void iniv(){ ll m = sqrt(N+0.5);st[1] = 1; for(ll i=2;i<=1000000;++i){ if(!st[i]){ prime[++tot] = i; if(i>m)continue; for(ll j=i*i;j<=1000000;j+=i)st[j] = 1; } } } bool vis[N]; ll fac(ll l,ll r){ ll ans = 0; memset(vis,0,sizeof vis); for(ll i=l;i<=r;++i){ ll x = arr[i],now = 1; while(x!=1){ if(x%prime[now]==0){ if(vis[prime[now]]==false){ vis[prime[now]] = true;ans++; } x/=prime[now]; } else now++; } } return ans; } ll G[N]; ll pop[N]; void solve(){ scanf("%lld",&n); ll cnt = 0,ans = 0; for(ll i=1;i<=n;++i){ scanf("%lld",&arr[i]); ll x = arr[i],now = 1; while(x>=prime[now]*prime[now]){ if(x%prime[now]==0){ if(G[prime[now]]==0){ pop[++cnt] = prime[now]; } ll d = i - G[prime[now]] - 1; ans -= (d*(d+1))/2; G[prime[now]] = i; while(x%prime[now]==0)x/=prime[now]; } now++; } if(x!=1){ if(G[x]==0)pop[++cnt] = x; ll d = i - G[x] - 1; ans -= (d*(d+1))/2; G[x] = i; } } ll t = (ll)((n*(n+1))/2); ans += cnt*t; //printf("%lld %lld %lld\n",cnt,t,ans); for(ll i=1;i<=cnt;++i){ ll d = n-G[pop[i]]; ans -= (d*(d+1))/2; } printf("%lld\n",ans); } int main(){ iniv(); solve(); return 0; }
我們隊的合數分解模板存在些問題,看來要給出來了(尤拉篩)
const int MAXN = 10000; int prime[MAXN+1]; void getPrime(){ memset(prime,0,sizeof prime); for(int i=2;i<=MAXN;++i){ if(!prime[i])prime[++prime[0]] = i; for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;++j){ prime[prime[j]*i]=1; if(i%prime[j]==0)break; } } } ll factor[100][2]; int fatCnt; int getFactors(ll x){ fatCnt = 0; ll tmp = x; for(int i=1;prime[i]<=tmp/prime[i];++i){ factor[fatCnt][1] = 0; if(tmp%prime[i]==0){ factor[fatCnt][0] = prime[i]; while(tmp%prime[i]==0){ factor[fatCnt][1]++; tmp/=prime[i]; } fatCnt++; } } if(tmp!=1){ factor[fatCnt][0] = tmp; factor[fatCnt][1] = 1; } return fatCnt; }
埃氏篩法見題解;需要注意的是,我們進行質因數分解,只需要分解到x>=prime[now]×prime[now];最後如果x!=1那麼x必是一個大於sqrt(x)的素數,有且只有一個,並且我們在分解的時候也不需要考慮x/prime[now]他是否是一個素數。
總結:這道題從一開始我們首先想到的是字首和,因為區間個數是n*(n+1)/2個;並且一個區間內的不同質因數個數並不滿足可加性,也就是說我們不能將他們放在一起去解題,這樣會增大我們的解題難度,於是開始思考題目本身,題目本身給了我們一個很好的暗示,既然要求的是關於質因數的,我們為什麼不挨個處理每一個質因數?(因為區間總數我們處理不了)今後要抓住題目所給的條件