UVALive 6912 Prime Switch 状压DP

Prime Switch

题目连接:

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4924

Description

There are lamps (uniquely numbered from 1 to N) and K switches. Each switch has one prime number
written on it and it is connected to all lamps whose number is a multiple of that prime number. Pressing
a switch will toggle the condition of all lamps which are connected to the pressed switch; if the lamp
is off then it will be on, and vice versa. You can press only one switch at one time; in other words,
no two switches can be pressed together at the same time. If you want to press multiple switches, you
should do it one by one, i.e. allowing the affected lamps of the previous switch toggle their condition
first before pressing another switch.
Initially all the lamps are off. Your task is to determine the maximum number of lamps which can
be turned on by pressing one or more switches.
For example, let there be 10 lamps (1 . . . 10) and 2 switches which numbers are 2 and 5 as shown
in the following figure.
In this example:
• Pressing switch 2 will turn on 5 lamps: 2, 4, 6, 8, and 10.
• Pressing switch 5 will turn on 2 lamps: 5 and 10.
• Pressing switch 2 and 5 will turn on 5 lamps: 2, 4, 5, 6, and 8. Note that lamp number 10 will
be turned off as it is toggled twice, by switch 2 and switch 5 (off → on → off).
Among all possible switches combinations, the maximum number of lamps which can be turned on
in this example is 5.

Input

The first line of input contains an integer T (T ≤ 100) denoting the number of cases. Each case begins
with two integers in a line: N and K (1 ≤ K ≤ N ≤ 1, 000), denoting the number of lamps and
switches respectively. The next line contains K distinct prime numbers, each separated by a single
space, representing the switches number. You are guaranteed that the largest number among those
switches is no larger than N

Output

For each case, output ‘Case #X: Y ’, where X is the case number starts from 1 and Y is the maximum
number of lamps which can be turned on for that particular case.
Explanation for 2nd sample case:
You should press switch 2 and 7, such that 11 lamps will be turned on: 2, 4, 6, 7, 8, 10, 12, 16, 18,
20, and 21. There exist some other combinations which can turn on 11 lamps, but none can turn more
than 11 lamps on.
Explanation for 3rd sample case:
There is only one switch, and pressing it will turn 20 lamps on.
Explanation for 4th sample case:
Pressing all switches will turn 42 lamps on, and it is the maximum possible in this case

Sample Input

4
10 2
2 5
21 4
2 3 5 7
100 1
5
100 3
3 19 7

Sample Output

Case #1: 5
Case #2: 11
Case #3: 20
Case #4: 42

Hint

题意

你有n盏灯,有m个开关,开关上面都写着一个质数

那么这个开关就控制着上面写着的数字的倍数。

灯泡按奇数次就亮着,偶数次,就熄灭。

问你最好情况下,最优有多少个灯亮着。

题解:

对于小于等于31的素数,我们状压去跑dp,对于大于的,我们就贪心。

因为大于31的素数一定是不会冲突的,因为上面的数乘起来就大于1000了。

然后这样就行了。

代码

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1000 + 15;
int N,K,pr[maxn],pre[maxn],prime[maxn],primelen,ha[maxn],tot,op[maxn],flag[maxn],temp[maxn];
vector < int > ap;

void Init(){
    memset( ha , -1 , sizeof( ha ) );
	for(int i = 2 ; i < maxn ; ++ i) if(!pre[i]){
		for(int j = i + i ; j < maxn ; j += i) pre[j] = 1;
		prime[ primelen ++ ] = i;
	}
}

int solve( int bit ){
	for(int i = 1 ; i <= N ; ++ i) flag[i] = 0;
	for(int i = 0 ; i < tot ; ++ i) if( bit >> i & 1 ){
		for(int j = op[i] ; j <= N ; j += op[i] ) flag[j] ^= 1;
	}
    for(auto it : ap){
    	int add = 0;
    	for(int i = it ; i <= N ; i += it) if( flag[i] == 0 ) ++ add ; else -- add;
    	if( add > 0 ) for(int i = it ; i <= N ; i += it) flag[i] ^= 1;
    }
    int rs = 0;
    for(int i = 1 ; i <= N ; ++ i) rs += flag[i];
    return rs;
}

int main(int argc,char *argv[]){
	int T,cas=0;
	Init();
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&N,&K);
		for(int i = 0 ; i < K ; ++ i) scanf("%d" , pr + i);
		sort( pr , pr + K );
		tot = 0;ap.clear();
		for(int i = 0 ; i < K ; ++ i) if( pr[i] <= 31 ) op[tot ++ ] = pr[i];else ap.push_back( pr[i] );
		int mx = 0;
		for(int i = 0 ; i < (1 << tot) ; ++ i) mx = max( mx , solve( i ) );
		printf("Case #%d: %d
", ++ cas , mx);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/qscqesze/p/5734130.html