2022 ICPC Gran Premio de Mexico 1ra Fecha (BDEF)

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022 ICPC Gran Premio de Mexico 1ra Fecha (BDEF)相关的知识,希望对你有一定的参考价值。

小技巧:
stoi(str,0,2) 将从0开始的二进制串转化为十进制串
不是标准函数,慎用(一般应该没问题吧……)

本次补的题应该都是铜、银牌题,可能欧洲场简单很多
D. Different Pass a Ports
好久没做快速幂的题目了,换了个题目背景,差点没看出来。
分析:
1.只要存在双向线路,便可去往别的港口,但不能停着不动。
2.港口间可重复访问。线路便可看作对矩阵的初始化。从港口1开始,需要初始化一个值为1的矩阵,每次对线路进行选择,即乘上初始化的矩阵。
分析下来,可简化为矩阵1*线路矩阵^k^

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
//const int N=7e5+5;
const int inf=1e18;
const int mod=1e9+7;
int fac[40];
int qpow(int a,int b)
    int res=1;
    while(b)
    
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    
    return res;

int getinv(int x)return qpow(x,mod-2);
int C(int a,int b)

    return (fac[a]*getinv(fac[a-b])%mod)*getinv(fac[b])%mod;

int n,m,k;
struct Matrix

	static const int N=102;  //开设的矩阵
	int a[N][N];
	Matrix(int e=0)          //矩阵清0
	
		for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            a[i][j]=e*(i==j);
	
	Matrix mul(Matrix A,Matrix B)   //矩阵的乘法运算   A*B
	
		Matrix ans(0);    //初始化全为0的矩阵
		for (int i=1;i<=n;i++)
        
			for (int j=1;j<=n;j++)
			
				for (int k=1;k<=n;k++)
							//模拟乘法运算
					ans.a[i][j]=(ans.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
				
			
		
		return ans;  //返回
	
	Matrix ksm(Matrix A,int b)
		Matrix ans(1);   //初始化为1的矩阵
		while (b)
        
			if (b&1)ans=mul(ans,A);   //快速幂
			A=mul(A,A);
			b>>=1;
		
		return ans;
	
;
Matrix A;
void solve()

    cin>>n>>m>>k;
    for(int i=1;i<=m;i++)
    
        int u,v;cin>>u>>v;
        A.a[u][v]=1;A.a[v][u]=1;
    
    Matrix B=A.ksm(A,k);
    int ans=0;
    for(int i=1;i<=n;i++)
        ans=(ans+B.a[1][i])%mod;
    cout<<ans<<endl;

signed main()

    ios;
    //int T;cin>>T;
    //while(T--)
        solve();
    return 0;


B. Building 5G antennas
思路:
1.f[v][dis]表示点v,对于当天的距离为j,最早可到达的天数。
2.使用set容器记录前一天可连接点的最小值,此处利用了set的自动排序功能。
3.每次将当天可到达的点记录下,压入到队列中,在都放入集合中。

#include<bits/stdc++.h>
//#define int long long
#define endl '\\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e5+5;
const int inf=1e18;
const int mod=1e9+7;
int fac[40];
int qpow(int a,int b)
    int res=1;
    while(b)
    
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    
    return res;

int getinv(int x)return qpow(x,mod-2);
int C(int a,int b)

    return (fac[a]*getinv(fac[a-b])%mod)*getinv(fac[b])%mod;

int n,k,f[N][105];
struct node

    int x,dis,fa;
;
bool vis[N];
vector<int>e[N],ans;
set<int>st;queue<node>q;

void solve()

    cin>>n>>k;
    for(int i=1;i<n;i++)
    
        int u,v;cin>>u>>v;
        e[u].push_back(v),e[v].push_back(u);
    
    for(int i=1;i<=n;i++) for(int j=0;j<105;j++) f[i][j]=inf;
    vis[1]=1;
    st.insert(1);           //set容器默认将小值放前面
    for(int i=0;i<n;i++)    //每天建造的网线
    
        if(!st.size()) break;
        int x=*st.begin();
        st.erase(st.begin());
        q.push(x,0,0);
        f[x][0]=i+1;
        ans.push_back(x);
        while(!q.empty())
        
            auto tmp=q.front();
            int u=tmp.x,dis=tmp.dis;
            q.pop();
            if(!vis[u])
            
                vis[u]=1;st.insert(u);
            
            if(dis<k)
            
                for(int v:e[u])
                
                    if(v==tmp.fa) continue;
                    if(f[v][dis+1]>f[u][dis])
                    
                        f[v][dis+1]=f[u][dis];
                        q.push(v,dis+1,u);
                    
                
            
        
    
    for(int x:ans) cout<<x<<" ";
    cout<<endl;

signed main()

    ios;
    //int T;cin>>T;
    //while(T--)
        solve();
    return 0;

E. Erudite of words
思路:
1.本题为数学推公式的题目。在M个字母中选取K个字母构成长度为N的字符串的方案数。
2.首先能想到从M个字母中选取k个字母为方案数为C(m,k)
3.长度为n,将k个字母随机放到n个位置。求出由k个字母构成的总方案数减去由c个字母构成的字符串(c<k)
4.f[i]表示由i个字母构成的长度为n的字符串。f[i]=i^n^-(1~j)*C(i,j)*f[j]的累加和
5.最后再乘上C(m,k)

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))

using namespace std;
const int N=1e6+5;
const int inf=1e18;
const int mod=1e9+7;
int n,m,k,fac[N],f[5005],inv[N];
int qpow(int a,int b)
    int res=1;
    while(b)
    
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    
    return res;

int getinv(int x)return qpow(x,mod-2);
int C(int a,int b)

    return (fac[a]*inv[a-b]%mod)*inv[b]%mod;

void init()

    fac[0]=1;
    for(int i=1;i<=N;i++) fac[i]=fac[i-1]*i%mod;
    /* 线性求逆元 受数据范围限制
    inv[1]=1;
    for(int i=2;i<n;i++)
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    */
    inv[N]=getinv(fac[N]);
    for(int i=N-1;i>=0;i--)
        inv[i]=inv[i+1]*(i+1)%mod;

void solve()

    init();
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++)
    
        f[i]=qpow(i,n)%mod;
        for(int j=1;j<i;j++)
            f[i]=(f[i]-C(i,j)*f[j]%mod+mod)%mod;
    
    cout<<f[k]*C(m,k)%mod<<endl;

signed main()

    ios;
    //int T;cin>>T;
    //while(T--)
        solve();
    return 0;


矩阵快速幂使用情况:
1.数据规模很大
2.有递推公式

F. Froginald the frog
需要再打一个表,能省很多时间。不然每一段都要进行一次快速幂,会tle。看的一篇题解也tle了,数据更新了,需要打表优化下。明天试试
思路:
1.被多个点分成了多个区间,答案为各个区间得累乘。
2.当两个点值差值为1时,到不了终点;为2、3时,只有一种情况;差值为4时有2种情况,符合斐波那契,eg:4、8,可行区间为【5,7】

#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))

using namespace std;
const int N=1e6+5;
const int inf=1e18;
const int mod=1e9+7;
int n,m,a[N];
struct Matrix

	static const int N=3;  //开设的矩阵
	int a[N][N];
	int n=2;
	Matrix(int e=0)          //矩阵清0
	
		for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            a[i][j]=e*(i==j);
	
	Matrix mul(Matrix A,Matrix B)   //矩阵的乘法运算   A*B
	
		Matrix ans(0);    //初始化全为0的矩阵
		for (int i=1;i<=n;i++)
        
			for (int j=1;j<=n;j++)
			
				for (int k=1;k<=n;k++)
							//模拟乘法运算
					ans.a[i][j]=(ans.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
				
			
		
		return ans;  //返回
	
	Matrix ksm(Matrix A,int b)
		Matrix ans(1);   //初始化为1的矩阵
		while (b)
        
			if (b&1)ans=mul(ans,A);   //快速幂
			A=mul(A,A);
			b>>=1;
		
		return ans;
	以上是关于2022 ICPC Gran Premio de Mexico 1ra Fecha (BDEF)的主要内容,如果未能解决你的问题,请参考以下文章

2019 ICPC Universidad Nacional de Colombia Programming Contest

2020 ICPC Universidad Nacional de Colombia Programming Contest---D

2017 ACM-ICPC, Universidad Nacional de Colombia Programming Contest K - Random Numbers (dfs序 线段树+数论)

2020 ICPC Universidad Nacional de Colombia Programming Contest---A

2022年,ICPC比赛CCPC比赛CCF-CSP考试蓝桥杯比赛天梯赛日程

2022年,ICPC比赛CCPC比赛CCF-CSP考试蓝桥杯比赛天梯赛日程