2012 Multi-University Training Contest 3

1001 質數篩選 判斷公共因子

題意:判斷A進制下的有限小數 能否轉化成B進制下的有限小數。

題解給的是,只需要判斷B中質因子是否包含A中質因子即可。不是很明白,後來問了羣裏的大牛,現在也算明白些了。

整數部分的互相轉換不用考慮,一定可以轉換的,A進制轉化成十進制的小數形式是(1/A + 1/A^2 + 1/A^3 + ... + 1/A^n) 係數不用考慮,想想十進制化二進制的時候是每次都乘以2取整什麼的,所以要化成B進制小數,並且保證最後是有限小數,那麼需要(1/A^x)*B^k  爲整數,()前的係數不影響,一個整數可以分解成p1^a1*p2*a2...pn^an(質因數分解)的形式,所以只要B的質因子包含A的質因子即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 1000010;
int isprime[maxn] = {0};
int prime[maxn];
ll ans[maxn];
int main() {
    int i , j;    
    for(i = 2 ; i*i < maxn ; i ++) 
        if(!isprime[i])
        for(j = i+i ; j < maxn ; j += i)
            isprime[j] = 1;
            int g = 0;
            for(i = 2 ; i < maxn ; i ++) {
                if(!isprime[i]) prime[g++] = i;    
            }
            int T;
            int cas = 1;
            scanf("%d",&T);
            while(T--) {
                ll t = 0;
                ll A , B;
                cin>>A>>B;
                int sus = 1;
                
                for(i = 0 ; prime[i]<=A && prime[i] ; i ++) {
                    int flag = 0;
                    if(A%prime[i]==0) {
                        if(B%prime[i]!=0) {
                            sus = 0;
                            break;    
                        }
                    }
                    while(A%prime[i]==0) A/=prime[i];
                }
                if(A!=1 && B%A!=0) sus = 0;  //A沒有約到1 但是每次約的時候 B也跟着除了 
                if(sus) printf("Case #%d: YES\n",cas++);
                else printf("Case #%d: NO\n",cas++);
            }
}

1005 判環

題意:給出一個有向圖圖,保證兩兩點之間一定有邊,求是否存在三個點的環。

思路:看官方題解。。。沒看明白,後來往上看的什麼判環。。畫了畫,果然,只要圖中有環,那麼一定存在三元環,因爲兩兩點之間必定有邊,可以用4個點5個點試試。所以用拓撲排序判環就行,但是用DFS判環一直TLE、、、

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 2010;
int map[maxn][maxn];
char s[maxn][maxn];
int main() {
    int T  , cas = 1;
    int indegree[maxn];
    scanf("%d",&T); 
    while(T--) {
        int n;
        memset(indegree , 0 , sizeof(indegree));
        scanf("%d",&n);
        int i , j;
        for(i = 1 ; i <= n ; i ++)
        scanf("%s",s[i]+1);
        for(i = 1 ; i <= n ; i ++) 
            for(j = 1 ; j <= n ; j ++) {
                map[i][j] = s[i][j] - '0';
                if(map[i][j]) {
                    indegree[j]++;
                    //printf("%d %d\n",i,j);
                }    
            }
            int k , m = 0;
            for(i = 1 ; i <= n ; i ++) {
                for(j = 1 ; j <= n ; j ++) {
                    if(indegree[j]==0) {
                        indegree[j] = -1;//刪點 
                        m++;
                        for(k = 1 ; k <= n ; k ++) {
                            if(map[j][k]) {
                                map[j][k] = 0;
                                indegree[k]--;
                            }    
                        }  
                        break;     
                    }    
                }
            }
            //printf("%d\n",m);
            if(m!=n) printf("Case #%d: Yes\n",cas++);
            else printf("Case #%d: No\n",cas++);
    }
}

還有一個。。。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 2010;
const int maxm = 2100000;
struct edge{
    int v;
    int nex;    
}e[maxm];
int k , head[maxn];
void addedge(int a , int b) {
    e[k].v = b;
    e[k].nex = head[a];
    head[a] = k++;
}
char s[maxn][maxn];
int indegree[maxn];
int main() {
    int T , cas = 1;
    scanf("%d",&T);
    while(T--) {
        int n;
        scanf("%d",&n);
        for(int i = 1 ; i <= n ; i ++)
        scanf("%s",s[i]+1);
        int a , b;
        k = 1;
        memset(head , -1 , sizeof(head));
        memset(indegree , 0 , sizeof(indegree));
        for(int i = 1 ; i <= n ; i ++) 
            for(int j = 1 ; j <= n ; j ++) {
                if(s[i][j]-'0'>0) {
                    a = i;
                    b = j;
                    addedge(a , b);
                    indegree[b]++;
                } 
            }
            int flag = 0 , p = 0;
            queue<int> q;
            for(int i = 1 ; i <= n ; i ++) {
                if(indegree[i]==0) { 
                    q.push(i);
                    p = 1;    
                }
            }
            if(!p) {
                printf("Case #%d: Yes\n",cas++);
                continue;    
            }
            int m = 0;
            while(!q.empty()) {
                int t = q.front();
                q.pop();
                m++;
                for(int j = head[t] ; j != -1 ; j = e[j].nex) {
                    int v = e[j].v;
                    indegree[v]--;
                    if(indegree[v]==0) q.push(v);
                }   
            }
            if(m!=n) printf("Case #%d: Yes\n",cas++);
            else printf("Case #%d: No\n",cas++);
    }    
}



1006 線段樹

題意:給出一些區間代表花開的時間段,詢問的時候給出時間點,問這個時候有多少花是開着的。

思路:線段樹+lazy+離散化

這道題看人人上思路後嘗試着自己搞,也是用的離散化,但是總超時。。。也許寫的也不對,後來就看別人沒有離散化的版本給A了,今天又看到這個

http://www.cnblogs.com/Yu2012/archive/2012/08/09/2630444.html  HH版本的線段樹 用的離散化。  發現我寫的還是有毛病,思路不清晰,細節不注意,總之線段樹還是不熟練。。。而且最坑爹的是寫的差不多了,cout ..2000ms+超時 printf直接過。。擦的

#include<iostream>
#include<cstdio>
#include<algorithm> 
using namespace std;
#define lson l , m , rt<<1
#define rson m + 1 , r , rt<<1|1
const int maxn = 100100;
int X[maxn<<2];
int li[maxn] , ri[maxn] , qq[maxn];
int add[maxn<<2];   //lazy
int sum[maxn<<2];   //該區間內出現了花開的次數 
int ans;
void Pushdown(int rt) { //節點編號 區間長度 
    if(add[rt]!=0) {        
        add[rt<<1] += add[rt];
        add[rt<<1|1] += add[rt];
        sum[rt<<1] += add[rt];
        sum[rt<<1|1] += add[rt];
        add[rt] = 0; 
        //printf("向下更新\n");
    }
}
int Bin(int key , int n , int X[]) {
    int l = 0;
    int r = n - 1;
    int m , k = -1;
    while(l <= r) {
        m = (l + r)>>1;
        if(key >= X[m]) {
            k = m;
            l = m + 1;    
        } else r = m - 1;
    }    
    return k;
}
void build(int l , int r , int rt) {
    add[rt] = 0;
    sum[rt] = 0;
    if(l == r) return;
    int m = (l + r)>>1;
    //printf("%d %d %d\n",l,r,rt);
    build(lson);
    build(rson);    
}
void Update(int L , int R , int l , int r , int rt) {
    //printf("%d %d %d %d %d\n",L,R,l,r,rt);
    if(L<=l && R>=r) {
        add[rt] ++;
        sum[rt] ++;
        return;    
    }
    Pushdown(rt);
    int m = (l + r)>>1;
    if(m >= L) Update(L , R , lson);
    if(m < R) Update(L , R , rson);
}
int Query(int L , int R , int l , int r , int rt) {
    if(L <= l && R >= r) {
        return sum[rt];
    }
    Pushdown(rt);
    //if(l == r) return sum[rt];
    int ret = 0;
    int m = (l + r)>>1;
    if(m >= L) ret += Query(L , R  , lson);
    if(m < R) ret += Query(L , R , rson);    
    return ret;
}
int main() {
    int T;
    int cas = 1;
    scanf("%d",&T);
    while(T--) {
        int u , q , i;
        scanf("%d%d",&u,&q);
        int g = 0;
        for(i = 0 ; i < u ; i ++) {
            scanf("%d%d",&li[i],&ri[i]);
            X[g++] = li[i];
            X[g++] = ri[i];
        }
        for(i = 0 ; i < q ; i ++) { 
            scanf("%d",&qq[i]);
            X[g++] = qq[i];
        }
        sort(X , X + g);
        int m = 1;
        for(i = 1 ; i < g ; i ++) {    //去重 
            if(X[i]!=X[i-1])
            X[m++] = X[i];    
        }
        build(0 , m , 1);
        for(i = 0 ; i < u ; i ++) {
            int l = Bin(li[i] , m , X);
            int r = Bin(ri[i] , m , X);
            Update(l , r , 0 , m , 1);    
        }
        int tq;
        printf("Case #%d:\n",cas++);
        for(i = 0 ; i < q ; i ++) {
            ans = 0;
            int key = Bin(qq[i] , m , X);    
            printf("%d\n",Query(key , key , 0 , m , 1));  //就這裏改成cout 超時坑死你! 
        }
    }    
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章