YBTOJ:灯光控制(贪心)(公倍数)(暴力枚举)
生活随笔
收集整理的這篇文章主要介紹了
YBTOJ:灯光控制(贪心)(公倍数)(暴力枚举)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 題目描述
- 解析
- 代碼
題目描述
解析
沒有想出來
首先可以確定開關要么開一次,要么不動,其他都和這倆是等價的
一開始最先想到的就是貪心的方法,每個開關遍歷,如果按下會使答案變好就按下。
但是顯然當前的開閉對后面是有后效性的,很容易就hack掉了
于是,我的思維就去了其他的天涯海角…
在正解的門前回了頭
qwq
因為都是質數,所以假設兩個開關x和y,它們一定互質
那么它們會互相影響的(也就是公倍數),一定是X*Y的整數倍
(諷刺的是這個我也發現了,就差拼在一起)
那么我們就可以發現:
對于所以大于根號n的開關,它們互相之間是不會互相影響的!
這是本題的關鍵性質
那么,我們如果確定了<=根號n的開關的狀態,后面的開關就可以使用貪心解決了
而我們又發現:<=根號n的質數非常至少,最多只有11個
dfs暴力枚舉所有可能狀態即可
問題得到解決
代碼
#include<bits/stdc++.h> #define ll long long //#define int long long using namespace std; const int N=1050; const int M=1e6; const int mod=1e9+7; int a[N],na,b[N],nb; int n,t,m,ans; int q[N]; int x[N]; void dfs(int k){if(k>na){for(int i=1;i<=n;i++) x[i]=0;for(int i=1;i<=na;i++){if(!q[i]) continue;int now=a[i];for(int j=now;j<=n;j+=now) x[j]^=1;}int tot=0;//printf("k=%d\n",k);for(int i=1;i<=n;i++) tot+=x[i];for(int i=1;i<=nb;i++){int now=b[i],val=0;for(int j=now;j<=n;j+=now){val += x[j]==0 ? 1 : -1;}if(val>0) {tot+=val;for(int j=now;j<=n;j+=now) x[j]^=1;}}ans=max(ans,tot);return;}q[k]=1;dfs(k+1);q[k]=0;dfs(k+1); } int main() {scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);ans=0;na=0;nb=0;for(int i=1;i<=m;i++){int o;scanf("%d",&o);if(o<floor(sqrt(n))) a[++na]=o;else b[++nb]=o;}dfs(1);printf("%d\n",ans);}return 0; }/* 4 10 2 2 5 21 4 2 3 5 7 100 1 5 100 3 3 19 7 */總結
以上是生活随笔為你收集整理的YBTOJ:灯光控制(贪心)(公倍数)(暴力枚举)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不定方程(质数与因数)
- 下一篇: 笔记本处理器还能比台式机更牛联想启天M5