2015 SWJTU ACM Summer Training Final Assessment 1st 部分题解

Problem A: Miss SOJ
题意:求满足n!%s^k最大的k
对s进行素因子分解,然后对每个素因子用n去除即可求出n!中此素因子的个数,取最小值更新答案即可。

#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <climits>

using namespace std;

const int MaxN = 1000005;

int cnt[1000005];

bool isPrime[MaxN];

long long tot, p[MaxN];

void getPrime()
{
    fill(isPrime, isPrime + MaxN, true);
    isPrime[0] = isPrime[1] = 0;
    tot = 0;
    for (int i = 2; i < MaxN; i++)
    {
        if (isPrime[i]) p[tot++] = i;
        for (int j = 0; j < tot; j++)
        {
            if (i * p[j] >= MaxN) break;
            isPrime[i * p[j]] = false;
            if (i % p[j] == 0) break;
        }
    }
}

int main()
{
    long long n,s,now,ans,tmp=0;
    int t,maxx;
    getPrime();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&n,&s);
        maxx=-1;
        for(int i=0; p[i]*p[i]<=s; ++i)
        {
            maxx=max(maxx,i);
            while(s%p[i]==0)
            {
                s/=p[i];
                ++cnt[p[i]];
            }
        }
        now=n;
        ans=LONG_LONG_MAX;
        if(s!=1)
        {
            tmp=0;
            while(now)
            {
                tmp+=now/s;
                now/=s;
            }
            ans=min(ans,tmp);
        }
        for(int i=0; i<=maxx; ++i)
        {
            if(cnt[p[i]])
            {
                now=n;
                tmp=0LL;
                while(now)
                {
                    tmp+=now/p[i];
                    now/=p[i];
                }
                ans=min(ans,tmp/cnt[p[i]]);
            }
        }
        printf("%lld\n",ans);
        memset(cnt,0,sizeof(cnt));
    }
    return 0;
}

Problem B: Longest Common Subsequence
题意:求LCS
LCS是O(N^2)的很容易得到TLE,可以考虑用map离散转为LIS,LIS的O(NlogN)的复杂度足以通过此题LIS nlogn 戳我

#include <cstring>
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#define MAXN 100005
using namespace std;

int b,a[MAXN],anss[MAXN];

map<int,int>ma;

template <class T>
int bsearch(T c[],int n,T a)
{

    int l=1, r=n;
    while(l<=r)
    {
        int mid = (l+r)/2;
        if( a > c[mid] && a <= c[mid+1] )
            return mid+1;
        else if( a < c[mid] )
           r = mid-1;
        else l = mid+1;
    }

}
template<class T>
int LIS(T a[], int n)
{

    int i, j, size = 1;
    T *c=new T[n+1];
    int *dp=new int[n+1];
    c[1] = a[1]; dp[1] = 1;

    for(i=2;i<=n;++i)
    {
        if( a[i] <= c[1] ) j = 1;
        else if( a[i] >c[size] )
            j=++size;
        else
            j = bsearch(c, size, a[i]);
        c[j] = a[i]; dp[i] = j;
    }
    return size;

}

int main()
{
    int n,cnt;
    while(cin>>n){
        ma.clear();
        cnt=1;
        memset(a,0,sizeof(a));
        memset(anss,0,sizeof(anss));
        for(int i=1;i<=n;++i){
            scanf("%d",a+i);
            ma[a[i]]=i;
        }
        for(int i=1;i<=n;++i){
            scanf("%d",&b);
            if(ma.count(b)!=0)anss[cnt++]=ma[b];
        }
        if(cnt==1){cout<<"0"<<endl;continue;}
        cout<<LIS(anss,cnt)<<endl;
    }
    return 0;
}

Problem D: Farmer John
裸的MST

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <numeric>

#define MAXN 2*100005

using namespace std;

int u[MAXN], v[MAXN], w[MAXN];
int p[MAXN], r[MAXN];

int n, m;

bool cmp(int i, int j) {
    return w[i] < w[j];
}
int find_(int x) {
    return p[x] == x ? x : p[x] = find_(p[x]);
}
long long Kruskal() {
    long long ans = 0;
    for(int i = 0; i < n + 1; i++) {
        p[i] = i;
    }
    for(int i = 0; i < m + n; i++) {
        r[i] = i;
    }
    sort(r, r + m + n, cmp);
    for(int i = 0; i < m + n; i++) {
        int e = r[i]; int x = find_(u[e]); int y = find_(v[e]);
        if(x != y) {
            ans += w[e]; p[x] = y;
        }
    }
    return ans;
}

int main() {
    while(scanf("%d%d", &n, &m) != EOF) {
        for(int i = 0; i < n; i++) {
            u[i] = 0;
            v[i] = i + 1;
            scanf("%d", &w[i]);
        }
         for (int i = n; i < m + n; ++ i) {
            scanf("%d%d%d", &u[i], &v[i], &w[i]);
        }
        printf("%lld\n", Kruskal());
    }
    return 0;
}

Problem E: Ticket and balance
三进制法,1表示放左,2表示放右,0表示不放,判机票价格可以通过取模比较

#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <climits>
#include <utility>

using namespace std;

int a,b,n,v[15];

long long ans,maxx;

vector <int> w;

vector <long long> vis;

int go(int a,vector <int>& w)
{
    w.clear();
    while(a)
    {
        w.push_back(a%3);
        a/=3;
    }
    return w.size();
}

long long pow_mod(long long a,long long b)
{
    long long ans=1;
    a%=7;
    while(b)
    {
        if(b&1LL)ans=(ans*a)%7;
        a=(a*a)%7;
        b>>=1;
    }
    return ans;
}

int my_pow(int n)
{
    int ans=1;
    for(int i=0;i<n;++i)ans*=3;
    return ans;
}

int main()
{
    while(scanf("%d%d%d",&a,&b,&n)==3)
    {
        vis.clear();
        for(int i=0;i<n;++i)scanf("%d",v+i);
        int cnt=my_pow(n);
        maxx=v[0];
        for(int i=0;i<cnt;++i)
        {
            int len=go(i,w);
            ans=0;
            for(int j=0;j<len;++j)
            {
                if(w[j]==1)ans+=v[j];
                else if(w[j]==2) ans-=v[j];
            }
            ans=ans<0?-ans:ans;
            maxx=max(ans,maxx);
            vis.push_back(ans);
        }
        sort(vis.begin(),vis.end());//此处为去重过程
        vis.erase(unique(vis.begin(),vis.end()),vis.end());
        long long tic=pow_mod((long long)a,(long long)b);
        if(tic==0||tic==6)tic=800;
        else tic=1000;
        printf("%lld %d %lld\n",tic,vis.size()-1,maxx);
    }
    return 0;
}

unique去重详解点我

Problem F: Sudoku
很裸的DLX,详见大白书P406

#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <strstream>
#include <map>
#include <set>
#include <queue>
#include <climits>
#include <utility>
#include <stdlib.h>

using namespace std;

int n;

struct DLX
{
    const static int maxn=20010;
    int n,sz;
    int S[maxn];
    int row[maxn],col[maxn];
    int L[maxn],R[maxn],U[maxn],D[maxn];
    int ansd,ans[maxn];

    void init(int n)
    {
        this->n=n;
        for(int i=0;i<=n;++i)
        {
            U[i]=i;
            D[i]=i;
            L[i]=i-1;
            R[i]=i+1;
        }
        R[n]=0;
        L[0]=n;
        sz=n+1;
        memset(S,0,sizeof(S));
    }

    void addRow(int r,vector <int> columns)
    {
        int first=sz;
        for(int i=0;i<columns.size();++i)
        {
            int c=columns[i];
            L[sz]=sz-1;R[sz]=sz+1;D[sz]=c;U[sz]=U[c];
            D[U[c]]=sz;U[c]=sz;
            row[sz]=r;col[sz]=c;
            S[c]++;sz++;
        }
        R[sz-1]=first;L[first]=sz-1;
    }

    #define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])

    void remove (int c)
    {
        L[R[c]]=L[c];
        R[L[c]]=R[c];
        FOR(i,D,c)
        FOR(j,R,i){U[D[j]]=U[j];D[U[j]]=D[j];--S[col[j]];}
    }

    void restore(int c)
    {
        FOR(i,U,c)
        FOR(j,L,i){++S[col[j]];U[D[j]]=j;D[U[j]]=j;}
        L[R[c]]=c;
        R[L[c]]=c;
    }

    bool dfs(int d)
    {
        if(R[0]==0){ansd=d;return true;}
        int c=R[0];
        FOR(i,R,0)if(S[i]<S[c])c=i;
        remove(c);
        FOR(i,D,c){
        ans[d]=row[i];
        FOR(j,R,i)remove(col[j]);
        if(dfs(d+1))return true;
        FOR(j,L,i)restore(col[j]);
        }
        restore(c);
        return false;
    }

    bool solve(vector <int>& v)
    {
        v.clear();
        if(!dfs(0))return false;
        for(int i=0;i<ansd;++i)v.push_back(ans[i]);
        return true;
    }
};

DLX slover;

const int SLOT=0;

const int ROW=1;

const int COL=2;

const int SUB=3;

int encode(int a,int b,int c){return a*n*n+b*n+c+1;}

void decode(int code,int& a,int& b,int& c)
{
    code--;
    c=code%n;code/=n;
    b=code%n;code/=n;
    a=code;
}

int puzzle[20][20];

int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n)==1)
    {
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                scanf("%d",&puzzle[i][j]);
            }
        }
        const int M=(int)sqrt(n);
        slover.init(n*n*4);
        for(int r=0;r<n;++r)
        {
            for(int c=0;c<n;++c)
            {
                for(int v=0;v<n;++v)
                {
                    if(puzzle[r][c]==0||puzzle[r][c]==v+1)
                    {
                        vector <int> coulumns;
                        coulumns.push_back(encode(SLOT,r,c));
                        coulumns.push_back(encode(ROW,r,v));
                        coulumns.push_back(encode(COL,c,v));
                        coulumns.push_back(encode(SUB,r/M*M+c/M,v));
                        slover.addRow(encode(r,c,v),coulumns);
                    }
                }
            }
        }
        vector <int> ans;
        if(slover.solve(ans))puts("Yes");
        else puts("No");
    }
    return 0;
}

Problem H: MMs
题意:M个结点的树,每个结点有一定数量的MMs,边有权值,询问使每个点一个MMs的最小花费,使用vector存邻接边,然后直接dfs即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <set>
#include <bitset>

using namespace std;

int n,m,u,v,w,c[100005];

int dep[100005];

long long ans;

vector <int> G[100005],W[100005];

bool vis[100005];

void dfs(int u)
{
    dep[u]=c[u]-1;vis[u]=true;
    int len=G[u].size(),w,v;
    for(int i=0;i<len;++i)
    {
        v=G[u][i];w=W[u][i];
        if(vis[v])continue;
        dfs(v);
        ans+=abs(dep[v])*(long long)w;
        dep[u]+=dep[v];
    }
}

int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=0;i<=n;++i){G[i].clear();W[i].clear();}
        memset(vis,false,sizeof(vis));
        for(int i=0;i<n-1;++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            G[u].push_back(v);
            G[v].push_back(u);
            W[u].push_back(w);
            W[v].push_back(w);
        }
        for(int i=1;i<=n;++i)scanf("%d",c+i);
        ans=0LL;dfs(1);
        printf("%lld\n",ans);
    }
    return 0;
}

Problem J: Hapsunday
签到题

#include <cstring>
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
using namespace std;

double a[66];

int main()
{
    for(int i=1;i<=64;++i){
        double sum=i;
        for(int j=1;j<=i+1;++j){
            sum/=j;
        }
        a[i]=sum;
    }
    int n;
    while(scanf("%d",&n)==1){
     double ans=0;
     for(int i=1;i<=n;++i){
        ans+=a[i];
     }
     printf("%.2lf\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
### 回答1: SWJTU计算机网络实验是指西南交通大学计算机网络课程的实践部分。该实验旨在帮助学生更好地理解和应用计算机网络理论知识,培养学生的实际动手能力和问题解决能力。 在SWJTU计算机网络实验中,学生需要完成一系列与计算机网络相关的实际操作和实验任务。这些任务包括网络配置、协议设置、网络性能测试等。学生将学习如何搭建和配置网络环境,理解网络协议的原理和实现方式,通过实际操作感受网络性能的变化和差异。 此外,SWJTU计算机网络实验还注重培养学生的团队合作精神和沟通能力。在实验中,学生通常需要分组合作完成任务,并要求进行组内交流和合作。通过协作完成任务,学生学会了如何与他人进行有效的沟通和协作,提高了解决问题的能力。 SWJTU计算机网络实验的目标是使学生在实践中深入理解计算机网络的原理和技术,并通过实验任务提升学生的实践能力和解决问题的能力。通过这些实验,学生可以更好地应用所学知识解决实际问题,为今后的学习和就业打下坚实的基础。 ### 回答2: SWJTU计算机网络实验是指西南交通大学计算机网络课程中的实践部分。该实验旨在让学生通过实际操作和调试,掌握计算机网络的基本原理和技术。 在SWJTU计算机网络实验中,学生将学习并实践诸如网络拓扑设计、网络设备配置、网络协议实现和网络故障排除等内容。实验中,学生将使用模拟器软件来创建和配置一个小型的计算机网络环境,通过模拟真实网络中的各种情况来进行实验。 实验内容包括但不限于以下几个方面:首先,学生需要了解和学习计算机网络的基本概念和原理,例如网络协议、TCP/IP模型、网络拓扑结构等。其次,学生需要了解如何使用模拟器软件来创建一个网络拓扑,并配置相应的网络设备,例如路由器、交换机等。然后,学生需要学习和实践网络协议的配置和实现,例如IP地址分配、路由设置、数据包转发等。最后,学生需要学习和实践网络故障排除的方法和技巧,例如使用命令行工具进行网络诊断和故障隔离。 通过SWJTU计算机网络实验,学生可以提升自己的实践能力和沟通能力。在实验过程中,他们会遇到各种网络问题和故障,需要自己进行分析和解决。此外,学生还可以与同学一起合作完成实验任务,共同解决实验中遇到的问题。 总之,SWJTU计算机网络实验是一项重要的实践环节,通过实际操作和调试,学生可以更好地掌握计算机网络的基本原理和技术。通过实验,学生可以提升自己的实践能力和团队合作能力,为今后的学习和工作打下良好的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值