cf 241D

题目大意:

给你n个数和p,都小于50000要求留下若干个数字,使得剩下的数字异或为0,并且从左到右串联起来可以被p整除,求一种这样的方案。

搜索

奇技淫巧题

我们无视排列中所有>25的元素。因为由1~25组成的异或和为0的方案有1048576个,已经远大于50000。在这么多种方案下,一个序列拼起来模p几乎可以看作是一个随机函数,异或和为0跟拼起来模p等于0之间几乎没有相关性。那也就是说我们在1~25之内找不到合法解的概率是
$\left ( \frac{49999}{50000} \right )^{1048576}\approx 7.8\ast 10^{-10}$
推广一下,假设只考虑所有≤2l2l的数,那么由1∼2l1∼2l组成的异或和为 00 的方案大约会有 22l2l22l2l 个。即总方案数 22l22l,除以总的结果方案数 2l2l(答案为0的只有12l12l 概率)

在如此大概率能找到解的情况下,可以通过本题。

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std; 
 4 
 5 #define rep(i,a,b) for(int i=a;i<=b;i++) 
 6 #define Rep(i,a,b) for(int i=a;i>=b;i--) 
 7 #define ms(i,a)    memset(a,i,sizeof(a))
 8 template<class T>void read(T &x){
 9     x=0; char c=0; 
10   while (!isdigit(c)) c=getchar(); 
11   while (isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar(); 
12 }
13 template<class T>void write(T x){
14   if(x>9) write(x/10); 
15   putchar(48+x%10); 
16 }
17 
18 int const maxn=26;  
19 int n,p,a[maxn],b[maxn],m,check,pos[maxn];  
20 
21 int inline pw(int x){
22   return x<10? 10:100;  
23 }
24 
25 void dfs(int k,int x,int y,int num){
26   if(x==0 && y==0 && num){
27     puts("Yes"); write(num);putchar('\n');  
28     rep(i,1,num) write(b[i]),putchar(' '); exit(0);  
29   } 
30   if(k>m) return ;
31   dfs(k+1,x,y,num);  
32   b[num+1]=pos[a[k]]; 
33   dfs(k+1,x^a[k],(y*pw(a[k])+a[k])%p,num+1);  
34 }
35 int main(){
36   read(n);read(p);  
37   rep(i,1,n){
38     int x;read(x); 
39     if(x<maxn) a[++m]=x,pos[x]=i;  
40   }
41   dfs(1,0,0,0);  
42   puts("No"); 
43   return 0; 
44 }

 

posted @ 2018-11-05 11:02  zjxxcn  阅读(198)  评论(0编辑  收藏  举报