NOI2015

I have long heard that NOI2015 questions are the easiest set of NOI questions. Even so, I still do super spicy chicken.

The program automatically analyzes this 'popular-' sb and check the set of questions, and I have nothing to say about the 'improved-' tree profile template question of the package manager .

 

The first question I encountered, which may be difficult to select, was the D1T3 sushi dinner.

The first reaction I saw was the model related to the bipartite graph in the network flow, but it has nothing to do with the bipartite graph.

I think it must have something to do with the root sign, but I rarely do such a question and I can't come up with any method.

Then give up treatment and fight violence, because prime numbers > n/2 can only appear in one number, so these prime numbers can be ignored, and only prime numbers with shape pressure <= n/2 can be used, there are 15 within 100, Then the 3-digit form pressed a violence, can you deceive 10 points more than 30 points of violence?

The positive solution is indeed related to the root sign. We consider that there are only 8 prime numbers <= sqrt(n), and each number contains at most one prime number > sqrt(n).

For numbers that do not contain primes > sqrt(n), we directly press dp, and for numbers containing primes > sqrt(n), we group them according to the number of primes, and press dp.

In the dp of each group, g[0/1][i][j] represents the number of schemes selected by the 0/1th person in this group.

The initial value of each group g[0][i][j]=g[1][i][j]=f[i][j]

The final answer f[i][j]=g[0][i][j]+g[1][i][j]-f[i][j] (minus this group of two people who have nothing not selected)

There seem to be a lot of questions that use the feature of "there is only one prime number containing > sqrt(n)", but I have written too few questions.

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=500+7,maxt=(1<<8)+7;
const ll prime[maxn]={2,3,5,7,11,13,17,19},totp=7,sz=(1<<8)-1;
ll n,mod,f[2][maxt][maxt],g[2][maxt][maxt],ans;

char cc; ll ff;
template<typename T>void read(T& aa) {
	aa=0;cc=getchar();ff=1;
	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

bool is_ok(int x) {
	For(i,0,totp) while(x%prime[i]==0) x/=prime[i];
	return x==1;
}

bool is_prime(int x) {
	for(int i=2;i*i<=x;++i) if(x%i==0) return 0;
	return 1;
}

void mo(ll& x) {if(x>=mod) x-=mod;}

int get_num(int x) {
	int rs=0;
	For(i,0,totp) if(x%prime[i]==0) rs|=(1<<i);
	return rs;
}

int main() {
	read(n); read(mod);
	int o=0,x,up,r; f[0][0][0]=1;
	For(i,2,n) if(is_ok(i)){
		o^=1; x=get_num(i);
//		For(s,0,sz) For(t,0,sz) f[o][s][t]=0;
		memset(f[o],0,sizeof(f[o]));
		For(s,0,sz) For(t,0,sz) if(f[o^1][s][t]) {
			f[o^1][s][t]%=mod;
			f[o][s][t]+=f[o^1][s][t];
			if(!(x&t)) f[o][s|x][t]+=f[o^1][s][t];
			if(!(x&s)) f[o][s][t|x]+=f[o^1][s][t];
		}
	}
	For(i,23,n) if(is_prime(i)) {
		o^=1; up=n/i;
		For(s,0,sz) For(t,0,sz) f[o][s][t]=mod-(f[o^1][s][t]%=mod);
		For(s,0,sz) For(t,0,sz) g[0][s][t]=g[1][s][t]=f[o^1][s][t];
		For(j,1,up) {
			x=get_num(j);
			Rep(s,sz,0) Rep(t,sz,0) if(!(x&t)) {
				r=g[0][s][t];
				g [0] [s | x] [t] + = r; mo (g [0] [s | x] [t]);
			}
			Rep(s,sz,0) Rep(t,sz,0) if(!(x&s)) {
				r=g[1][s][t];
				g [1] [s] [t | x] + = r; mo (g [1] [s] [t | x]);
			}
		}
		For(s,0,sz) For(t,0,sz)
			f[o][s][t]=(f[o][s][t]+g[0][s][t]+g[1][s][t])%mod;
	}
	For(s,0,sz) For(t,0,sz) ans+=f[o][s][t];
	printf("%lld\n",ans%mod);
	return 0;
}

 

The second question I encountered that may have provincial difficulty is D2T1 Homer Epic

Seeing this question and thinking that I might be able to make it out, I feel like it's actually quite to my taste ( if I remember the Haverman tree )

And it's not that I haven't done this kind of "combined" type of questions, maybe I have A few more?

Later, I wrote a dp like O(n^2log(n)), and I expected 45 to write down and only 30.

I first think of this question as selecting n positions on the trie tree, and there is no ancestor-grandchild relationship between these n positions, so the depth is the length.

Because we know that if n positions are determined, then the depth with more occurrences must be small.

Then we consider the depth to increase from small to large. dp[i][j] represents the minimum cost of processing to the point with the largest number of occurrences at present, and there are j positions in this layer . len[i][j] represents processing to the point with the largest number of occurrences. A layer has j positions to choose the minimum depth at minimum cost.

Initially dp[0][k]=w[1], len[0][k]=1

When calculating dp[i], then enumerate how much the depth of this point is more than the depth of the previous point. If the number of optional positions is >=ni, you don't need to go further.

The positive solution is the k-forked Huffman tree. Note that the number should be supplemented to a multiple of (k-1) at the beginning.

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=1e5+7;
ll n,k,ans;

char cc; ll ff;
template<typename T>void read(T& aa) {
	aa=0;cc=getchar();ff=1;
	while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

struct Node{
	ll dep,w;
	Node(){}
	Node(ll dep,ll w):dep(dep),w(w){}
	bool operator < (const Node& b) const{return w==b.w? dep>b.dep:w>b.w;}
}O;

priority_queue<Node> G;

int main() {
	read(n); read(k); ll x,d;
	For(i,1,n) {
		read(x);
		G.push(Node(0,x));
	}
	if((n-1)%(k-1)!=0) Rep(i,k-1-(n-1)%(k-1),1) G.push(Node(0,0));
	while(G.size()>1) {
		x=0; d=0;
		For(i,1,k) {
			o=G.top(); G.pop();
			x+=o.w; d=max(d,o.dep);
			ans+=ow;
		}
		G.push(Node(d+1,x));
	}
	o = G.top ();
	printf("%lld\n%lld\n",ans,o.dep);
	return 0;
}

 

As for the wine tasting...

I have done it twice before, this is the 3rd time, here is a link: http://www.cnblogs.com/Serene-shixinyi/p/8321281.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324973931&siteId=291194637