B:序列的与和
WY是一个序列大师,他喜欢研究一些和序列相关的操作。时间长了,WY对某一些特定的序列产生了感情,换句话说,WY喜欢和这些特定的序列打交道。比如说WY最近就迷上了这样一类序列:
我们规定序列的与和定义为序列中所有元素按位与得到的结果。
如序列 [1,2,3] :其与和结果为1&2&3=0.
若一个序列与和的结果,其二进制表示形式下包含 k 个 1 ,WY则会认为这是他喜欢的序列
现在WY的手里有一个序列了,他想知道,这个的序列的非空子序列中有多少个他喜欢的序列。由于WY已经非常熟悉这类序列了,所以他想考考你,看看你是否能解决这个问题。
子序列定义为:从原序列中去除几个(可以为零个)元素后得到的序列。
输入:
第一行两个正整数, n 和 k :
分别表示序列元素个数 n ,以及WY喜欢的序列类型的与和,在其二进制形式下包含 1 的个数 k。
第二行 n个 数,表示给定的序列元素 ai。
数据范围:
1<=n<=20,0<=k<=20,0<=ai<=2^64-1.
输出:
对于每个测试样例输出一个数字,表示你统计的满足要求的子序列的个数。
示例1
输入
1. 3 6 2. 2 4 1
输出
0
说明
对于样例,其子序列有:
[2]:其与和为10(二进制),仅包含一个1,不为6,所以对答案贡献为零
[2,4]:与和为 0 ,同理,贡献为零。
[2,1]:与和结果0
[2,4,1]:与和结果0
[4]:与和结果100
[4,1]:与和结果0
[1]:与和结果1
综上,答案为0。
思路:深度优先搜索,直接遍历就行了,(比赛时候一直在想子序列公式,吐了)
int a[30],sum=0,n,k; void find(int x,int y) { if(__builtin_popcount(y)==k)//统计该数在二进制下1的个数 sum++; for(int i=x+1;i<=n;i++) find(i,y&a[i]); } void solve() { cin>>n>>k; for(int i=1;i<=n;i++) { cin>>a[i]; } for(int i=1;i<=n;i++) find(i,a[i]); cout<<sum<<endl; return ; }
D:幂运算
小 T 最近在学习离散数学,书上有一句话:
n 个命题变项只能生成 2^2^n 个真值不同的命题公式。
现在小 T 想要知道,对于两个给定的正整数 n, p, n 个命题变项在模 p 意义下能生成多少个真值不同的命题公式?
形式化的说,对于两个给定的正整数 n, p: 计算 2^2^n mod p的值
取模运算的定义为a mod b=a−⌊a/b⌋×b
数据保证 1≤n≤1e6,1≤p≤2 31−1
输入描述:
一行,两个正整数 n, p
输出描述:
一行,一个整数表示2^2^n mod p
示例1
输入
3 1223
输出
256
思路:从2开始直接一直翻倍取模n次就行(看写的少,没开,原来是个水题。。。。。)
void solve() { int n,p,sum=2; cin>>n>>p; while(n--) { sum=(sum*sum)%p; } cout<<sum<<endl; return ; }
E:平均数
小 A 是一个刚上大学的大一新生,作为新时代的年轻人, 聚餐自然不会像 80 后一样抢着请客,而是优先考虑 AA
现在有一次聚餐,一共消费了 S 元, 在座共有 n 人, 因为大家觉得 1.99 这样的金额不够整,看上去很不爽,所以大家都只会出整数金额的钱
为了尽可能公平, 不妨设第 i 个人给了 ai元, 你需要使 an这个数列的方差尽可能小, 同时满足 ∑i=1 nai=S
给定 n, S, 要求你给出一个不下降序列 an 在满足∑i=1nai=S 的情况下使得这个数列的方差尽可能小
对于所有数据,保证1≤n≤1e6,1≤S≤1e18
输入描述:
第一行,两个正整数 n, S
输出描述:
一行, n 个整数表示 ai, 中间用空格隔开
示例1
输入
7 30
输出
4 4 4 4 4 5 5
思路:直接s/n算出每个人的最低花费,s%n从后往前每人加上1,直到s%n减为零(签到)
void solve() { int n,aa,b,s,c; cin>>n>>s; aa=s/n; c=n-1; for(int i=0;i<n;i++) a[i]=aa; b=s%n; while(b--) { a[c]++; c--; } for(int i=0;i<n;i++) cout<<a[i]<<" "; return ; }