jQuery火箭图标返回顶部代码 - 站长素材
jQuery火箭图标返回顶部代码 - 站长素材

2019.10.16 解题报告

T1:a

【题目描述】

对于给定的一个正整数\(n\), 判断n是否能分成若干个正整数之和 (可以重复) ,其中每个正整数都能表示成两个质数乘积。

【输入描述】

第一行一个正整数 \(q\),表示询问组数。
接下来 \(q\) 行,每行一个正整数 \(n\),表示询问。

【输出描述】

\(q\) 行,每行一个正整数,为$ 0$ 或 \(1\)\(0\) 表示不能,\(1\) 表示能。

【输入样例】

\(5\)
\(1\)
\(4\)
\(5\)
\(21\)
\(25\)

【输出样例】

\(0\)
\(1\)
\(0\)
\(1\)
\(1\)

【样例解释】

\(4=2*2\)
\(21=6+15=2*3+3*5\)
\(25=6+9+10=2*3+3*3+2*5\)
\(25=4+4+4+4+9=2*2+2*2+2*2+2*2+3*3\)

【数据范围】

\(30\%\)的数据满足:\(q\leq 20,n\leq 20\)
\(60\%\)的数据满足:\(q\leq 10000,n\leq 5000\)
\(100\%\)的数据满足:\(q\leq 10^5,n\leq 10^{18}\)

Solution

\(n \leq 20\) 时,只有\(1,2,3,5,7,11\)无解,其余均有解。
\(n > 20\) 时,因为\(n = (n-4) + 4 = (n-4) + 2 * 2\),而\((n-4)\)这个数\(\geq 16\),是一定有解的。
所以,我们证明了对于任意的正整数\(n\),
只有\(n = 1,2,3,5,7,11\)时无解,其余均有解。
那么我们只需要在每组数据中判断一下n是否等于\(1,2,3,5,7,11\)中的任意一个即可。
复杂度\(O(q)\).

Code
//****定理 
#include <cstdio>
#include <iostream>
using namespace std;
int q;
long long x;
long long read() {
	long long s = 0, w = 1;
	char ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') w = -1;ch = getchar();}
	while(isdigit(ch)) {s = s * 10 + ch - '0';ch = getchar();}
	return s * w; 
}
int pd(int x) {
	if(x == 4) return 1;
	if(x == 6) return 1;
	if(x == 8) return 1;
	if(x == 9) return 1;
	if(x == 10) return 1;
	if(x == 12) return 1;
	return 0;
}
int main() {
	freopen("a.in", "r", stdin);
	freopen("a.out", "w", stdout);
	q = read();
	while(q--) {
		x = read();
		if(x <= 12) 
			if(pd(x)) printf("1\n");
			else printf("0\n");
		else printf("1\n");
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}
 

T2:b

【题目描述】

有一个长度为\(n\)的自然数序列\(a\),要求将这个序列恰好分成至少\(m\) 个连续子段。 每个子段的价值为该子段的所有数的按位异或。要使所有子段的价值按位与的结果最大,输出这个最大值。

【输入描述】

第一行一个正整数 \(q\),表示询问组数。
接下来$ q$ 组输入,每组输入两行:
第一行两个正整数 \(n,m\)
第二行 $n $个正整数,描述序列 \(a\)

【输出描述】

一行一个正整数,表示答案。

【输入样例】

\(1\)
\(5\) \(3\)
\(1\) \(2\) \(3\) \(4\) \(5\)

【输出样例】

\(1\)

【数据范围】

\(20\%\)的数据:\(n\leq 20\)
\(40\%\)的数据:\(n\leq 100,a_i<256\)
\(60\%\)的数据:\(n\leq 100\)
\(100\%\)的数据:\(1\leq q\leq 12,1\leq m\leq n\leq 1000,0\leq a_i<2^{30}\)

Solution

因为异或运算具有交换律且(\(x\)异或\(x = 0\)),所以区间异或和可以由两个前缀异或和异或得到。
考虑从高位到低位确定答案的二进制位,然后考虑判断是否能分成至少\(m\)段。
如何判断是否能分成至少\(m\)段?
"能分成至少\(m\)段"与"最多能分成的段数\(\geq m\)"等价。
\(dp[i] = a[1..i]\)这一段数最多能分成多少段"
转移就是直接枚举上一段的末尾j,如果\([j+1,i]\)可以组成一段,那么就把\(dp[i] = max(dp[i],dp[j] + 1)\);
这样\(DP\)的复杂度是\(O(n^2)\)
总复杂度就是\(O(q * log(值域) * DP) = O(30qn^2) \approx 3.6 * 10^8\),因为常数较小可以过。

值得一提的是,直接\(O(N^3)DP\)是错误的。因为它不满足最优子结构。
Code

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

int q,n,m,ans,x,s[1005],f[1005];

int rd(){
	int re=0,f=1;char c=getchar();
	while ((c<'0')||(c>'9')) {if (c=='-') f=-f;c=getchar();}
	while ((c>='0')&&(c<='9')) {re=re*10+c-'0';c=getchar();}
	return re*f;
}

int Max(int x,int y){
	return ((x>y)?x:y);
}

int main(){
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
	q=rd();
	for (;q>0;--q){
		n=rd();m=rd();
		s[0]=0;
		for (int i=1;i<=n;++i){
			x=rd();s[i]=s[i-1]^x;
		}
		
		ans=0;
		for (int i=29;i>=0;--i){
			memset(f,0,sizeof(f));
			f[0]=1;
			for (int j=1;j<=n;++j){
				for (int k=0;k<j;++k) if (f[k]>0){
					x=s[j]^s[k];
					if (((ans&x)>=ans)&&((x&(1<<i))>0))
						f[j]=Max(f[k]+1,f[j]);
				}
			}
			if (f[n]>m) ans|=(1<<i);
		}
		
		cout<<ans<<'\n';
	}
	return 0;
}

T3:c

【题目描述】

定义一个排列 \(a\) 的价值为满足\(|a[i]-i|\leq 1\)\(i\)的数量。
给出三个正整数 \(n,m,p\),求出长度为$ n $且价值恰好为 \(m\) 的排列的个数对 \(p\)
模的结果。

【输入描述】

第一行两个正整数 \(T,p\),$T \(为数据组数,\)p $为模数。
接下来 \(T\) 行,每行两个正整数 \(n,m\)

【输出描述】

$T $行,每行一个非负数,表示答案。

【输入样例】

\(5\) \(1887415157\)
\(3\) \(1\)
\(3\) \(2\)
\(3\) \(3\)
\(50\) \(10\)
\(1500\) \(200\)

【输出样例】

\(1\)
\(2\)
\(3\)
\(621655247\)
\(825984474\)

【数据范围】

\(10\%\)的数据:\(n\leq 10\)
\(30\%\)的数据:\(n\leq 15\)
\(50\%\)的数据:\(n\leq 200\)
另有 \(10\%\)的数据:\(m=1\)
另有$ 10%\(的数据:\)m=n-1$
\(100\%\)的数据:\(1\leq T,n,m\leq 2000,2\leq p\leq 10^{12}\)

Solution:

题解:
因为\(n,m \leq 2000\),而且\(p\)是事先给出的,所以我们可以一次性预处理出\(n,m\leq 2000\)的答案。

考虑一个长度为\(i\)的排列如何变成长度为\(i+1\)的排列。
一种情况是我在它末尾加入了一个数\(i+1\),另一种情况是我用\(i+1\)替换掉了原来排列中的一个数,然后把被换掉的数放到排列的末尾。
那么,这个排列权值的变化就是:
第一种情况:在它末尾加入了一个数\(i+1\),权值\(+1\)
第二种情况:用\(i+1\)替换掉一个数,权值 \(+=\) 加的贡献$ -$ 换掉的数的贡献。

\(DP\)当中,我们只需要考虑替换掉的数是否是\(i\),以及\(i\)是否在位置\(\frac{i}{i-1}\)即可。总共有\(5\)种本质不同的状态,分类讨论转移即可。
复杂度\(O(nm)\)

Code:
#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N=2005;

int q,n,m,u,v;
LL p,ans,f[N][N][5],x;

int rd(){
	int re=0,f=1;char c=getchar();
	while ((c<'0')||(c>'9')) {if (c=='-') f=-f;c=getchar();}
	while ((c>='0')&&(c<='9')) {re=re*10+c-'0';c=getchar();}
	return re*f;
}

int main(){
	freopen("c.in","r",stdin);
	freopen("c.out","w",stdout);
	cin>>q>>p;
	memset(f,0,sizeof(f));
	f[1][1][0]=1ll;
	f[2][2][0]=1ll;f[2][2][1]=1ll;
	
	n=2000;
	for (int i=2;i<n;++i)
		for (int j=0;j<=n;++j){
			for (int k=0;k<=4;++k){
				x=f[i+1][j+1][0]+f[i][j][k];
				x=(x<p)?x:(x-p);
				f[i+1][j+1][0]=x;
				u=j+((k%2)==0);
				v=1+(k!=0);
				x=f[i+1][u][v]+f[i][j][k];
				x=(x<p)?x:(x-p);
				f[i+1][u][v]=x;
			}
			
			if (f[i][j][0]>0ll){
				f[i+1][j-1][4]=(f[i+1][j-1][4]+f[i][j][0]*(LL)(j-1))%p;
				f[i+1][j][4]=(f[i+1][j][4]+f[i][j][0]*(LL)(i-j))%p;
			}
			if (f[i][j][1]>0ll){
				x=f[i+1][j][3]+f[i][j][1];
				x=(x<p)?x:(x-p);
				f[i+1][j][3]=x;
				f[i+1][j-1][4]=(f[i+1][j-1][4]+f[i][j][1]*(LL)(j-2))%p;
				f[i+1][j][4]=(f[i+1][j][4]+f[i][j][1]*(LL)(i-j))%p;
			}
			if (f[i][j][2]>0ll){
				x=f[i+1][j][3]+f[i][j][2];
				x=(x<p)?x:(x-p);
				f[i+1][j][3]=x;
				f[i+1][j-1][4]=(f[i+1][j-1][4]+f[i][j][2]*(LL)(j-1))%p;
				f[i+1][j][4]=(f[i+1][j][4]+f[i][j][2]*(LL)(i-j-1))%p;				
			}
			if (f[i][j][3]>0ll){
				x=f[i+1][j+1][3]+f[i][j][3];
				x=(x<p)?x:(x-p);
				f[i+1][j+1][3]=x;
				f[i+1][j-1][4]=(f[i+1][j-1][4]+f[i][j][3]*(LL)(j-1))%p;
				f[i+1][j][4]=(f[i+1][j][4]+f[i][j][3]*(LL)(i-j-1))%p;	
			}
			if (f[i][j][4]>0ll){
				x=f[i+1][j+1][3]+f[i][j][4];
				x=(x<p)?x:(x-p);
				f[i+1][j+1][3]=x;		
				if (j>0) f[i+1][j-1][4]=(f[i+1][j-1][4]+f[i][j][4]*(LL)(j))%p;
				f[i+1][j][4]=(f[i+1][j][4]+f[i][j][4]*(LL)(i-j-2))%p;	
			}
		}
	
	for (;q>0;--q){
		cin>>n>>m;
		ans=(f[n][m][0]+f[n][m][1]+f[n][m][2]+f[n][m][3]+f[n][m][4])%p;
		cout<<ans<<'\n';
	}
	return 0;
}

谢谢收看,祝身体健康!

posted @ 2019-10-16 14:55  lzpclxf  阅读(197)  评论(0编辑  收藏  举报