一直覺得codeforces上的題解法都很新奇,這個也不例外,說說題意,
最大10^5的數,進行10^5次操作,每一次進行加入或者刪除一個數,加入時:只有與已加入的數互素才能加入,不能加入的,輸出原因(與某個不互素,或者,已經加入)。刪除時:輸出刪除成功,或者尚未加入。
這個題看起來不簡單,經過分析之後,我發現,對於10^5這麼大的數,只能最多有7個不同的素數的冪的積的形式,要使互素,也就是說,沒有共同的素數因子,按照這個思路,我們對每一個數的素數因子進行標記,插入的時候,就可以查詢插入的這個數的素數因子有沒有出現
這個思路的時間複雜度是O(10^5*7),這個複雜度是可以解決的。
但是,其中有一個需要輸出與第幾個互素,這個也需要標記。ok,代碼見下面
#include <iostream>#include <stdio.h>#include <string.h>using namespace std;#define N 1000010int prime[N];bool isPrime[N+1];int size;void getPrime() { size = 0; memset(isPrime,true,sizeof(isPrime)); int i; for(i=2; i<=N/2; i++) { if(isPrime[i]) //i是素數 for(int j=i+i; j<=N; j+=i) isPrime[j]=0; } for(i=2; i<=N; i++) { if(isPrime[i]) prime[size++]=i; }}bool active[100010];int data[100010][10];int count[100010];//計數出現這個素數的jint main(){ //cout << 2*3*5*7*11*13*17; getPrime(); for(int i = 0;i < size;i++) { for(int j = prime[i];j < 100010;j += prime[i]) data[j][ ++data[j][0] ] = prime[i]; } int n,m; scanf("%d%d",&n,&m); memset(active,0,sizeof(active)); memset(count,0,sizeof(count)); char c[2];int t; for(int i = 0;i < m;i++) { scanf("%s%d",c,&t); if(c[0] == '+') { //1 success 2 already on 3衝突 if(active[t]) printf("Already on\n"); else { bool b = 0; for(int j = 1;j <= data[t][0];j++) if(count[ data[t][j] ]) { printf("Conflict with %d\n",count[ data[t][j] ]); b = 1;break; } if(!b) { for(int j = 1;j <= data[t][0];j++) count[ data[t][j] ] = t; printf("Success\n"); active[t] = 1; } } }else //-- { if(!active[t]) printf("Already off\n"); else { for(int j = 1;j <= data[t][0];j++) count[ data[t][j] ] = 0; printf("Success\n"); active[t] = 0; } } } return 0;}