zoukankan      html  css  js  c++  java
  • 数论基础题

    LightOJ - 1370(欧拉公式)

    也就是欧拉公式板子题吧

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll MAXN = 1e6 + 10;
    
    ll phi[MAXN + 1];
    void euler(int n) {
    	for(int i = 2; i <= n; ++i)	phi[i] = i;
    	for(int i = 2; i <= n; ++i) {
    		if(phi[i] == i) {
    			for(int j = i; j <= n; j+=i) {
    				phi[j] = phi[j] / i * (i - 1);
    			}
    		}
    	}
    }
    int main () {
    	euler(MAXN);
    	int T;
    	scanf("%d", &T);
    	int n;
    	int i = 0;
    	while(T--) {
    		scanf("%d", &n);
    		ll ans = 0;
    		while(n--) {
    			ll x;
    			scanf("%lld", &x);
    			ll temp = x + 1;
    			while(phi[temp] < x) {
    				temp++;
    			}
    			ans += temp;
    		}
    		printf("Case %d: %lld Xukha
    ", ++i, ans);
    	}
    }
    

    第二道题就有点儿恶心了。。。LightOJ - 1356。题意:给出一系列数,求出最大的子集使得子集中每个元素两两相除(大的除以小的)得到的结果不能是素数。

    解题思路:建图求得最大的独立集(一些好的关于二分图的博客如下)

    https://www.cnblogs.com/lucianosimon/p/9415848.html

    https://blog.csdn.net/Wall_F/article/details/8248373

    https://www.cnblogs.com/lucianosimon/p/9415848.html

    https://blog.csdn.net/ErrorNam/article/details/82976377?utm_medium=distribute.pc_relevant.none-task-blog-searchFromBaidu-6.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-searchFromBaidu-6.control

    不过做这道题之前先来道Hdu 2389(作为二分图匹配HK算法的板子题,原理以后弄懂了再讲,当初离散还是学得太浅了)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll MAXN = 3000 + 10;
    const ll MAXM = MAXN * MAXN;
    const ll INF = 0x3f3f3f3f;
    struct Edge
    {
    	int v;
    	int nxt;
    }edge[MAXM];
    struct node
    {
    	double x, y;
    	double v;
    }a[MAXN], b[MAXN];
    ll nx, ny, cnt, t, dis;
    ll first[MAXN], xlink[MAXN], ylink[MAXN];
    ll dx[MAXN], dy[MAXN];
    ll vis[MAXN];
    
    void init() {
    	cnt = 0;
    	memset(first, -1, sizeof first);
    	memset(xlink, -1, sizeof xlink);
    	memset(ylink, -1, sizeof ylink);
    }
    
    void addEdge(ll u, ll v) {
    	edge[cnt].v = v;
    	edge[cnt].nxt = first[u];
    	first[u] = cnt++;
    }
    
    double dist(const node a, const node b) {
    	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }
    
    int bfs() {
    	queue<int> q;
    	dis = INF;
    	memset(dx, -1, sizeof dx);
    	memset(dy, -1, sizeof dy);
    	for(int i = 0; i < nx; ++i) {
    		if(xlink[i] == -1) {
    			q.push(i);
    			dx[i] = 0;
    		}
    	}
    	while(!q.empty()) {
    		int u = q.front();
    		q.pop();
    		if(dx[u] > dis) {
    			break;
    		}
    		for(int e = first[u]; e != -1; e = edge[e].nxt) {
    			int v = edge[e].v;
    			if(dy[v] == -1) {
    				dy[v] = dx[u] + 1;
    				if(ylink[v] == -1) {
    					dis = dy[v];
    				} else {
    					dx[ylink[v]] = dy[v] + 1;
    					q.push(ylink[v]);
    				}
    			}
    		}
    	}
    	return dis != INF;
    }
    
    int find(int u) {
    	for(int e = first[u]; e != -1; e = edge[e].nxt) {
    		int v = edge[e].v;
    		if(!vis[v] && dy[v] == dx[u] + 1) {
    			vis[v] = 1;
    			if(ylink[v] != -1 && dy[v] == dis) {
    				continue;
    			}
    			if(ylink[v] == -1 || find(ylink[v])) {
    				xlink[u] = v;
    				ylink[v] = u;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int MaxMatch() {
    	int ans = 0;
    	while(bfs()) {
    		memset(vis, 0, sizeof vis);
    		for(int i = 0; i < nx; ++i) {
    			if(xlink[i] == -1) {
    				ans += find(i);
    			}
    		}
    	}
    	return ans;
    }
    
    int main () {
    	int T;
    	int times = 0;
    	scanf("%d", &T);
    	while(T--) {
    		printf("Scenario #%d:
    ", ++times);
    		init();
    		int Time;
    		scanf("%d", &Time);
    		scanf("%d", &nx);
    		for(int i = 0; i < nx; ++i) {
    			scanf("%lf%lf%lf", &a[i].x, &a[i].y, &a[i].v);
    		}
    		scanf("%d", &ny);
    		for(int i = 0; i < ny; ++i) {
    			scanf("%lf%lf", &b[i].x, &b[i].y);
    		}
    		for(int i = 0; i < nx; ++i) {
    			for(int j = 0; j < ny; ++j) {
    				double limit = a[i].v * Time;
    				double s = dist(a[i], b[j]);
    				if(s <= limit) {
    					addEdge(i, j);
    				}
    			}
    		}
    		int ans = MaxMatch();
    		printf("%d
    
    ", ans);
    	}
    }
    

    直接看这道题,自己写了HK算法,然后交了一发

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll MAXN = 40000 + 10;
    const ll MAXM = 40000;
    const ll INF = 0x3f3f3f3f;
    int prime[MAXN];
    bool isPrime[MAXN];
    struct Edge
    {
    	int v;
    	int nxt;
    }edge[MAXM];
    struct node
    {
    	double x, y;
    	double v;
    }a[MAXN], b[MAXN];
    ll nx, ny, cnt, dis;
    ll first[MAXN], xlink[MAXN], ylink[MAXN];
    ll dx[MAXN], dy[MAXN];
    ll vis[MAXN];
    std::vector<int> v1;
    std::vector<int> v2;
    
    int v[MAXN];
    void init() {
    	memset(edge, 0, sizeof edge);
    	memset(a, 0, sizeof a);
    	memset(b, 0, sizeof b);
    	cnt = 0;
    	memset(first, -1, sizeof first);
    	memset(xlink, -1, sizeof xlink);
    	memset(ylink, -1, sizeof ylink);
    	v1.clear();
    	v2.clear();
    }
    void firstinit() {
    	memset(prime, 0, sizeof prime);
    	memset(isPrime, 0, sizeof isPrime);
    	memset(v, 0, sizeof v);
    	int m = 0;
    	for(int i = 2; i <= MAXN; ++i) {
    		if(v[i] == 0) {
    			v[i] = i;
    			prime[++m] = i;
    			isPrime[i] = 1;
    		}
    		for(int j = 1; j <= m; ++j) {
    			if(prime[j] > v[i] || prime[j] > MAXN / i) {
    				break;
    			}
    			v[i * prime[j]] = prime[j];
    		}
    	}
    }
    void addEdge(ll u, ll v) {
    	edge[cnt].v = v;
    	edge[cnt].nxt = first[u];
    	first[u] = cnt++;
    }
    
    
    int bfs() {
    	queue<int> q;
    	dis = INF;
    	memset(dx, -1, sizeof dx);
    	memset(dy, -1, sizeof dy);
    	for(int i = 0; i < nx; ++i) {
    		if(xlink[i] == -1) {
    			q.push(i);
    			dx[i] = 0;
    		}
    	}
    	while(!q.empty()) {
    		int u = q.front();
    		q.pop();
    		if(dx[u] > dis) {
    			break;
    		}
    		for(int e = first[u]; e != -1; e = edge[e].nxt) {
    			int v = edge[e].v;
    			if(dy[v] == -1) {
    				dy[v] = dx[u] + 1;
    				if(ylink[v] == -1) {
    					dis = dy[v];
    				} else {
    					dx[ylink[v]] = dy[v] + 1;
    					q.push(ylink[v]);
    				}
    			}
    		}
    	}
    	return dis != INF;
    }
    
    int find(int u) {
    	for(int e = first[u]; e != -1; e = edge[e].nxt) {
    		int v = edge[e].v;
    		if(!vis[v] && dy[v] == dx[u] + 1) {
    			vis[v] = 1;
    			if(ylink[v] != -1 && dy[v] == dis) {
    				continue;
    			}
    			if(ylink[v] == -1 || find(ylink[v])) {
    				xlink[u] = v;
    				ylink[v] = u;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int MaxMatch() {
    	int ans = 0;
    	while(bfs()) {
    		memset(vis, 0, sizeof vis);
    		for(int i = 0; i < nx; ++i) {
    			if(xlink[i] == -1) {
    				ans += find(i);
    			}
    		}
    	}
    	return ans;
    }
    
    int divide(int n) {
    	int m = 0;
    	for(int i = 2; i <= sqrt(n); ++i) {
    		if(n % i == 0) {
    			//m++;
    			while(n % i == 0) {
    				n /= i;
    				m++;
    			}
    		}
    	}
    	if(n > 1) {
    		m = 1;
    	}
    	return m;
    }
    
    int main () {
    	firstinit();
    	int T;
    	scanf("%d", &T);
    	int t = 0;
    	while(T--) {
    		init();
    		int N;
    		scanf("%d", &N);
    		for(int i = 0; i < N; ++i) {
    			int temp;
    			scanf("%d", &temp);
    			if(divide(temp) & 1) {
    				v1.push_back(temp);
    			} else {
    				v2.push_back(temp);
    			}
    		}
    
    		nx = v1.size();
    		ny = v2.size();
    
    		for(int i = 0; i < v1.size(); ++i) {
    			for(int j = 0; j < v2.size(); ++j) {
    				if(max(v1[i], v2[j]) % min(v1[i], v2[j]) == 0 && isPrime[max(v1[i], v2[j]) / min(v1[i], v2[j])] == 1) {
    					addEdge(i, j);
    				} 
    			}
    		}
    		int ans = MaxMatch();
    		ans = N - ans;
    		printf("Case %d: %d
    ", ++t, ans);
    	}
    }
    

    好了已经会套用板子了,然后进行一些细节上的建图优化就可以A了(毒瘤题)

    
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int N=5e5+10;
    const int INF=0x3f3f3f3f;
    int a[N];
    vector<int> G[40005];//大了会超空间
    int n;
     
     
    bool prime[N];//prime[i]表示i是不是质数 
    int p[N], tot;//p[N]用来存质数,tot记录有多少个质数 
    void init(){//预处理所有的质数 
        for(int i = 2; i < N; i ++) prime[i] = true;//初始化为质数 
        for(int i = 2; i < N; i++){
            if(prime[i]) p[tot ++] = i;//把质数存起来 
            for(int j = 0; j < tot && i * p[j] < N; j++){
                prime[i * p[j]] = false;
                if(i % p[j] == 0) break;//保证每个合数被它最小的质因数筛去 
            }
        }    
    }
     
     
    int pos[N];
    int B[N];
    void solve(){
    	for(int i=1;i<=n;++i){
    		int cnt=0,cnt2=0;//第一个记录质因子个数,第二个是总共因子的个数 
    		int temp=a[i];//先存下来原来的数 
    		for(int j=0;p[j]*p[j]<=temp;j++){
    			if(temp%p[j]==0){//找到质因子 
    				B[cnt++]=p[j];
    				while(temp%p[j]==0){
    					temp/=p[j];
    					cnt2++;
    				}
    			}
    		}
    		if(temp>1){//最后一个特判 
    			B[cnt++]=temp;
    			cnt2++;
    		} 
    		for(int j=0;j<cnt;++j){//对每一个质因子考虑 
    			temp=pos[a[i]/B[j]];
    			if(temp<=i&&temp!=-1){//如果该数除去质因子后的数在集合里面,并且在当前数字的前面(排序过了) 
    				if(cnt2%2) G[i].push_back(temp);//按照因子个数的奇偶建图 
    				else G[temp].push_back(i);
    			}
    		}
    	}
    }
     
    //HK算法求最大匹配 
    int cx[N],cy[N],visited[N],dy[N],dx[N];
    int dis;
    int bfs()
    {
        queue<int> Q;
        dis = INF;
        memset(dx,-1,sizeof(dx));
        memset(dy,-1,sizeof(dy));
        for(int i=1; i<=n; i++)
        {
            if(cx[i] == -1)
            {
                Q.push(i);
                dx[i] = 0;
            }
        }
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop();
            if(dx[u] > dis) break;
            for(int v=0; v<G[u].size(); v++)
            {
                int i = G[u][v];
                if(dy[i] == -1)
                {
                    dy[i] = dx[u] + 1;
                    if(cy[i] == -1) dis = dy[i];
                    else
                    {
                        dx[cy[i]] = dy[i] + 1;
                        Q.push(cy[i]);
                    }
                }
     
            }
        }
        return dis != INF;
    }
     
    int find(int u)
    {
        for(int v=0; v<G[u].size(); v++)
        {
            int i = G[u][v];
            if(!visited[i] && dy[i] == dx[u] + 1)
            {
                visited[i] = 1;
                if(cy[i] != -1 && dis == dy[i]) continue;
                if(cy[i] == -1 || find(cy[i]))
                {
                    cy[i] = u;
                    cx[u] = i;
                    return 1;
                }
            }
        }
        return 0;
    }
    int match(){
    	int ans=0;
    	memset(cx,-1,sizeof(cx));
    	memset(cy,-1,sizeof(cy));
    	while(bfs()){
    		memset(visited,0,sizeof(visited));
    		for(int i=1;i<=n;++i)
    			if(cx[i]==-1&&find(i))
    				ans++;
    	}
    	return ans;
    }
     
     
    int main(){
    	int T;
    	scanf("%d",&T);
    	init(); 
    	for(int kcase=1;kcase<=T;kcase++){
    		for(int i=0;i<40005;++i)
    			G[i].clear();
    		memset(pos,-1,sizeof(pos));//初始化 
    		scanf("%d",&n);
    		for(int i=1;i<=n;++i)
    			scanf("%d",&a[i]);
    		sort(a+1,a+1+n);
    		for(int i=1;i<=n;++i)
    			pos[a[i]]=i;//排序编号 
    		solve();//建图 
    		printf("Case %d: %d
    ",kcase,n-match());		
    	}
    	return 0;
    }
    

    LightOJ - 1341(线性筛优化+唯一分解定理+质因数分解)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll MAXN = 1e6 + 10;
    ll v[MAXN], prime[MAXN];
    ll m;
    void primes(int n) {
    	memset(v, 0, sizeof v);
    	m = 0;
    	for(int i = 2; i <= n; ++i) {
    		if(v[i] == 0) {
    			v[i] = i;
    			prime[++m] = i;
    		}
    		for(int j = 1; j <= m; ++j) {
    			if(prime[j] > v[i] || prime[j] > n / i) {
    				break;
    			}
    			v[i * prime[j]] = prime[j];
    		}
    	}
    }
    
    ll divide(ll n) {
    	ll temp = 0;
    	ll s = 1;
    	for(ll i = 1; prime[i] < n && i <= m; ++i) {
    		temp = 0;
    		if(n % prime[i] == 0) {
    			//m++;
    			while(n % prime[i] == 0) {
    				n /= prime[i];
    				temp++;
    			}
    		}
    		s *= (temp + 1);
    	}
    	if(n > 1) {
    		s *= 2;
    	}
    	return s;
    }
    
    int main () {
    	primes(MAXN);
    	int T;
    	scanf("%d", &T);
    	int t = 0;
    	while(T--) {
    		ll a, b;
    		scanf("%lld%lld", &a, &b);
    		// cin >> a >> b;
    		ll ans = 0;
    		if(b * b > a) {
    			ans = 0;
    		} else {
    			ll cnt = 0;
    			for(ll i = 1; i < b; ++i) {
    				if(a % i == 0) {
    					cnt++;
    				} 
    			}
    			ans = divide(a) / 2 - cnt;
    		}
    		printf("Case %d: %lld
    ", ++t, ans);
    	}
    	
    }
    
  • 相关阅读:
    vuex详解
    es6 数组方法的扩展
    es6class语法和继承
    变量的解构赋值
    es6变量let
    前端模块化
    webpack基础
    react中的redux(入门)
    react-router-dom中的BrowserRouter和HashRouter和link与Navlink
    react-router-dom
  • 原文地址:https://www.cnblogs.com/lightac/p/14185907.html
Copyright © 2011-2022 走看看