codechef December Challenge 2014

  第二题与第三题想法+对类似的dp一点小小的看法

  第二题:就是求K与给定数组子串异或和的异或值的最大值

                数据范围  1<=k,ai<=1000N<=1000

  第三题:就是问是否能够把N个数分为K堆,并且使得每一堆的数的总和相等。

                数据范围 N<=21 ,K<=8 ,每个数<=10^10

  弱弱看法:明显第二题就是一个区间dp,因为数组每个数最大为1000,所以最大的异或值不大于4000。

                    所以就是类似于凑金币的dp思想,每个数有选或不选两种可能。最后把所有可能的异或和值

                    与K异或就可以得到最大的了。

                    首先考虑从N个数中是否可以选若干个数,总和为N/K ?每个数也有选或不选两种,但是注意

                    到数组的数大到10^10,所以dp的就行不通了,对于如此小的N,就DFS咯,至于怎么DFS

       去凑出K堆数,思路还是很好想出来的,就不贴代码了。

   所以分析数据范围,及复杂度还是有利于解题的(~~~~~@@废话~~~~)

加上后面的几道题,代码比赛结束后再贴   QAQ

  1,2题就自己脑补吧。。。

  第三题代码:(注意:数的序列也会影响dfs的结果,比如:4 4 5 6 8 3 3 6,dfs出来就是no)

#include <stdio.h>
typedef long long int LLI;

#define MAX_N 32
LLI a[MAX_N];
int mark[MAX_N];

#define MAX_K 16
LLI s[MAX_K];

int n, k;
LLI part;


int searchRec(int indexS, int nextIndex) {
	if (s[indexS] == part) {
		if (indexS == (k - 2)) return 1;
		return searchRec(indexS + 1, n - 1);
	}

	int i, ok;
	LLI r;
	for (i = nextIndex; i >= 0; --i) {
		if (mark[i]) continue;
		r = s[indexS] + a[i];
		if (r <= part) {
			mark[i] = 1;
			s[indexS] += a[i];
			ok = searchRec(indexS, i - 1);
			mark[i] = 0;
			s[indexS] -= a[i];
			if (ok) return 1;
		}
	}

	return 0;
}

int calc(LLI sum) {
	if (k == 1) return 1;
	if (n < k) return 0;
	if ((sum % k)!=0) return 0;

	part = sum / k;

	int i;
	for (i = 0; i < k; ++i) s[i] = 0;
	for (i = 0; i < n; ++i) mark[i] = 0;

	s[0] = a[n - 1];
	if (part < s[0]) return 0;
	mark[n - 1] = 1;

	return searchRec(0, n - 1);
}


int main() {
	int t, i;
	LLI sum, r;

	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		scanf("%d", &k);
		sum = 0;
		for (i = 0; i < n; ++i) {
			scanf("%lld", &r);
			sum += r;
			a[i] = r;
		}
		if (calc(sum)) printf("yes\n"); else printf("no\n");
	}
	return 0;
}


  第四题代码:(dp计数)

 

#include<stdio.h>

long long int p=1000000007;

int main()
{
	long long int n,i,j,k,t,q,arr[110],nar[110],mat[110][110];
	scanf("%lld",&n);
	for(i=0;i<n;i++)
	{
		scanf("%lld",arr+i);
	}
	k=0;
	for(i=0;i<n;i++)
	{
		int fg=1;
		if(fg)
		{
			nar[k]=arr[i];
			k++;
		}
	}
	n=k;
	for(i=0;i<110;i++)
	{
		for(j=0;j<110;j++)
		{
			mat[i][j]=1;
		}
	}
	for(i=1;i<n;i++)
	{
		if(nar[i]>0)
		{

			t=i;
			q=0;
			for(j=(i-1);j>=0;j--)
			{
				if(nar[j]==(-nar[i]))
				{
					mat[j][i]=mat[j][i-1]+(q*mat[j][t-1])+mat[j+1][i-1];
					mat[j][i]=mat[j][i]%p;
					q=(q*mat[j][t-1])+mat[j+1][i-1];
					q=q%p;
					t=j;
				}
				else
				{
					mat[j][i]=mat[j][i-1]+(q*mat[j][t-1]);
					mat[j][i]=mat[j][i]%p;				
				}
			}
		}
		else
		{
			for(j=(i-1);j>=0;j--)
			{
				mat[j][i]=mat[j][i-1];
			}
		}
	}
	printf("%lld\n",(mat[0][n-1]%p+p)%p);
	return 0;
}
第5题代码(就一个dfs,我是写的在线LCA)

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int NN=5+1e4;
int n,k,rt;
vector<int> G[NN],val[105];
int depth,bn,b[NN*2],f[NN*2],p[NN];
int dis[NN];
void dfs(int u,int fa)
{
    int tmp=++depth;
    b[++bn]=tmp; f[tmp]=u; p[u]=bn;
    for (int i=0; i<G[u].size(); i++)
    {
        int v=G[u][i];
        if (v==fa) continue;
        dis[v]=dis[u]+1;
        dfs(v,u);
        b[++bn]=tmp;
    }
}

int dp[NN*2][20];
void rmq_init(int n)
{
    for (int i=1; i<=n; i++) dp[i][0]=b[i];
    int m=floor(log(n*1.0)/log(2.0));
    for (int j=1; j<=m; j++)
      for (int i=1; i<=n-(1<<j)+1; i++)
          dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int l,int r)
{
    int k=floor(log((r-l+1)*1.0)/log(2.0));
    return min(dp[l][k],dp[r-(1<<k)+1][k]);
}

int LCA(int a,int b)
{
    if (p[a]>p[b]) swap(a,b);
    int k=rmq(p[a],p[b]);
    return f[k];
}
void init()
{
         memset(dis,0,sizeof(dis));
         for(int i=0;i<NN;i++)
                  G[i].clear();
         for(int i=0;i<105;i++)
                  val[i].clear();
         bn=depth=0,dis[rt]=0;
}
int main()
{
         //freopen("in.txt","r",stdin);
         int u,v,vv,Q;
         init();
         scanf("%d%d%d",&n,&k,&rt);
         for(int i=1;i<n;i++){
                  scanf("%d%d",&u,&v);
                  G[u].push_back(v);
                  G[v].push_back(u);
         }
         for(int i=1;i<=n;i++){
                  scanf("%d",&vv);
                  val[vv].push_back(i);
         }
         dfs(rt,0);
         rmq_init(bn);
         scanf("%d",&Q);
         while(Q--){
                  scanf("%d%d",&v,&vv);
                  int ans,lca,_max=-1,len=val[vv].size();
                  for(int i=0;i<len;i++){
                         u=val[vv][i];
                         /*if(u==v){
                            ans=v;
                            break;
                         }*/
                         lca=LCA(v,u);
                         //printf("v=%d u=%d lca=%d\n",u,v,lca);
                         if(dis[lca]>=_max){
                            if(dis[lca]==_max) {
                                    ans=min(ans,u);
                                    continue;
                            }
                            _max=dis[lca];
                            ans=u;
                         }
                  }
                  printf("%d\n",ans);
         }
         return 0;
}

第7题代码(数论,找规律,还不会~~)

#include<bits/stdc++.h>
using namespace std;
const int p=1000000007;
typedef long long ll;
int pm(ll a,int n){
	int r=1;
	for(;n;n>>=1,a=a*a%p)
	if(n&1)r=r*a%p;
	return r;
}
int f[10000001];
int main(){
	int T,N,M,L,R;
	for(cin>>T;T--;){
		cin >> N >> M >> L >> R;
		ll y=1;
		for(int j=M,l=1;j>=L;--j){
			ll tmp= M/j!=l?y=pm(l=M/j,N):y;
			for(int k=j+j;k<=M;k+=j)tmp-=f[k];
			f[j]=tmp%p;
		}
		cout << (accumulate(f+L,f+R+1,0LL)%p+p)%p << endl;
	}
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值