CodeCraft-20 (Div. 2)(C(本原多项式) D (BFS) E (状压+dp))

题目链接

C. Primitive Primes

题意:

给定两个多项式 相乘得到h(x)的多项式,求h多项式中某个系数不能p整除,输出这个系数的位置

做法:什么是本原多项式?献上百度百科

只能说这个题跟本源多项式的定义很像,本原多项式保证了一定有解,由于

C_{k}=\sum_{s+t=k}A_{s}*B_{t}

做法就是 两个多项式第一个系数不被mod整除的位置加起来,因为如果前面都能呗mod整除,第n+m这个位置的卷积都是从前面卷积过来的,前面都被mod整除,那么构成 C_{n+m}其他系数就是 被mod整除的,仅仅是第i项 和第j项相乘不是mod的倍数

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
const int N=1e6+10;
const ll mod=1e9+7;
ll a[N],b[N],n,m,p,ans1,ans2;
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}
int main()
{
    n=input();
    m=input();
    p=input();
    rep(i,1,n) a[i]=input();

    for(int i=1;i<=n;i++)
    if(a[i]%p&&ans1==0) ans1=i;

    rep(i,1,m) b[i]=input();

    for(int i=1;i<=m;i++)
    if(b[i]%p&&ans2==0) ans2=i;

    printf("%lld\n",ans1+ans2-2);
}

D. Nash Matrix

题意:题意:你有一个n*n的棋盘,每个格子都有一个操作:往上走U,往下走D,往左走L,往右走R,呆在原地X,现在要构造这个棋盘。

现在给出从每个格子开始走最后会停在的地方(x,y),如果x=-1,y=-1,代表一直循环下去;然后让你输出每个格子是哪种操作,如果不存在就输出INVALID。

做法:从呆着原地的格子开始bfs找到一些路径,再从(-1,-1)的位置开始bfs一下,由于无限循环走只需要两个相邻的格子都是(-1,-1)就能实现了,也是简单的bfs一下即可

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

typedef pair<int,int> P;
const int N=1e3+10;
pair<int,int> ma[N][N];
char ans[N][N];
char s[5]="ULDR";
int vis[N][N],dir[4][2]={1,0,0,1,-1,0,0,-1};

int fll=1,n;

void bfs(P p){
	queue<P> que;
	que.push(p);
	ans[p.first][p.second]='X';
	vis[p.first][p.second]=1;
	while(que.size()){
		P np=que.front();que.pop();
		for(int i=0;i<4;i++){
			int x=np.first+dir[i][0];
			int y=np.second+dir[i][1];
			if(x<1||x>n||y<1||y>n)continue;
			if(vis[x][y]) continue;
			if(ma[x][y]!=p) continue;
            vis[x][y]=1;
            ans[x][y]=s[i];
            que.push(P(x,y));
		}
	}
}
void bfs1(P p){
	queue<P> que;
	que.push(p);
	vis[p.first][p.second]=1;
	int f=0;
	while(que.size()){
		P np=que.front();que.pop();
		for(int i=0;i<4;i++){
			int x=np.first+dir[i][0];
			int y=np.second+dir[i][1];
			if(x<1||x>n||y<1||y>n)continue;
			if(vis[x][y]) continue;
			if(ma[x][y]!=P(-1,-1))continue;

            if(!f){
                f=1;
                ans[p.first][p.second]=s[(i+2)%4];
            }

            vis[x][y]=1;
            ans[x][y]=s[i];
            que.push(P(x,y));
		}
	}
	fll&=f;
}

int main(){
	scanf("%d",&n);
	rep(i,1,n)
	rep(j,1,n)
    scanf("%d %d",&ma[i][j].first,&ma[i][j].second);

	rep(i,1,n)
	rep(j,1,n)
    if(!vis[i][j]&&ma[i][j]==P(i,j))	bfs(P(i,j));

	rep(i,1,n)
	rep(j,1,n)
    if(!vis[i][j]&&ma[i][j]==P(-1,-1))	bfs1(P(i,j));



	rep(i,1,n)
	rep(j,1,n)
    if(!vis[i][j])	fll=0;

	if(!fll)	puts("INVALID");
	else{
		puts("VALID");
		rep(i,1,n){
            rep(j,1,n)	printf("%c",ans[i][j]);
			puts("");
		}
	}
	return 0;
}
/*
2
1 1 -1 -1
2 2 2 2
*/

E. Team Building

题意:大意:n个人,选k个观众,p个球员,每个人当观众的能力为ai, 在每个位置的能力为s[i][j],让你选择p+k 个人使得能力和最大。

不太会写,搜的题解:来源


两个条件如果分开讨论的话,

只考虑a[i]  直接把a从大往小排序选前k个即可,

只考虑选球员,p<=7  状压一下,套个dp转移一下就行。

这里就是两个合在一起了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n,p,k;
ll dp[N][(1<<7)],s[N][10],a[N],d[N];
bool cmp(int x,int y)
{
    return a[x]>a[y];
}
int main()
{
    scanf("%d%d%d",&n,&p,&k);
    for(int i=1;i<=n;++i) {
        scanf("%d",&a[i]);
        d[i]=i;
    }
    for(int i=1;i<=n;++i)
    for(int j=1;j<=p;++j) scanf("%d",&s[i][j]);
    sort(d+1,d+1+n,cmp);

    memset(dp,-1,sizeof(dp));
    dp[0][0]=0;
    int len=1<<p;
    for(int i=1;i<=n;++i){
        for(int j=0;j<len;++j){
            int t=0;
            for(int q=0;q<p;++q) if((1<<q)&j) t++;

            if(i-1-t>=k&&dp[i-1][j]!=-1) dp[i][j]=dp[i-1][j];//选满了
            else if(i-1-t<k&&dp[i-1][j]!=-1)
                dp[i][j]=max(dp[i][j],dp[i-1][j]+a[d[i]]);//没选满 由于a[i]排了序,所以这里必定选才是最大
        }

        for(int j=0;j<len;++j)
        for(int q=0;q<p;++q)
            if(!((1<<q)&j)&&dp[i-1][j]!=-1)
            dp[i][j|(1<<q)]=max(dp[i][j|(1<<q)],dp[i-1][j]+s[d[i]][q+1]);

    }
    //printf("dp[1][0]:%lld dp[1][1]:%lld\n",dp[1][0],dp[1][1]);

    printf("%lld\n",dp[n][(1<<p)-1]);
    return 0;
}
发布了498 篇原创文章 · 获赞 66 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/104673150