日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LA2965侏罗纪(异或和为0的最大数字个数)

發布時間:2025/6/17 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LA2965侏罗纪(异或和为0的最大数字个数) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 給你n個字符串,讓你在里面找到一個字符串集合使得這些字符串中所有的字母出現的次數和為偶數,輸出集合的最大個數,和ASCII最小的解。


思路:
? ? ? 考慮到每個字符串中所有的字符都是有大寫字母組成的,我們可以把每個字符串都用一個26位長的二進制數表示,比如第一位表示A,那么當第一位為0的時候就是說明A出現了偶數次,1表示出現了奇數次(直接異或),那么我們要找到滿足題意的集合也就是可以轉化成我們在n個26位長的二進制數中找到最多的數字,使得他們異或一起最后等于0(等于0表示所有的字母都是偶數次),這樣我們有兩種方式,一種是我自己寫的暴搜,時間復雜度O(2^n)沒有超時,如果是要完全的暴力建議去寫搜索,不要寫for循環枚舉,因為for的枚舉在判斷的時候時間復雜度還要*n,這樣估計就超時了,寫搜索可以在狀態轉換的時候把值算出來,這樣最后的時候不用可以去算什么,直接if判斷,減少了一個n,時間復雜度應該是妥妥的O(2^n),還有就是再說下白書上的方法,用的是中途相遇法,這個方法感覺很好,讓我想起了雙向廣搜,這個題目我想是不是應該叫雙向深搜,大體思路就是把要枚舉的東西分成兩部分分別枚舉,然后在結合一起去判斷,時間復雜度可以降低不少,白書給的時間復雜度我感覺算的有問題,我算的是O(1.44^n*n/2),兩個方法我都試了,中途相遇法的時間復雜度優化了很多,下面是兩個方法的AC代碼。






直接暴力深搜 時間復雜度
O(2^n) ?runtime ?2.292?


#include<map>
#include<string>
#include<stdio.h>
#include<string.h>


using namespace std;


int num[30];
char str[1100];
int Ans ,Anszt;


void DFS(int nowid ,int nows ,int nownum ,int nowzt)
{
? ?if(nowid == 0)
? ?{
? ? ? if(nownum == 0)
? ? ? {
? ? ? ? ?if(Ans <= nows)
? ? ? ? ?{
? ? ? ? ? ? Ans = nows;
? ? ? ? ? ? Anszt = nowzt;
? ? ? ? ?}
? ? ? }
? ? ? return ;
? ?}
? ?DFS(nowid - 1 ,nows ,nownum ,nowzt * 2);
? ?DFS(nowid - 1 ,nows + 1 ,nownum ^ num[nowid] ,nowzt * 2 + 1);
}


int main ()
{
? ?int n ,i ,j ,now;
? ?while(~scanf("%d" ,&n))
? ?{
? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? {
? ? ? ? ?scanf("%s" ,str);
? ? ? ? ?now = 0;
? ? ? ? ?int l = strlen(str) - 1;
? ? ? ? ?for(j = 0 ;j <= l ;j ++)
? ? ? ? ?now = now ^ (1 << (str[j] - 'A'));
? ? ? ? ?num[i] = now;
? ? ? }
? ? ? Ans = Anszt = 0;
? ? ? DFS(n ,0 ,0 ,0);
? ? ? printf("%d\n" ,Ans);
? ? ? int nowid = 1 ,mk = 0;
? ? ? while(Anszt)
? ? ? {
? ? ? ? ?if(Anszt&1)?
? ? ? ? ?{
? ? ? ? ? ? if(mk) printf(" %d" ,nowid);
? ? ? ? ? ? else printf("%d" ,nowid);
? ? ? ? ? ? mk = 1;
? ? ? ? ?}
? ? ? ? ?Anszt /= 2;
? ? ? ? ?nowid ++;
? ? ? }
? ? ? printf("\n");
? ?}
? ?return 0;
}
? ?


中途相遇法 ?時間復雜度
O(2^(n/2)*n/2) => 1.44^n*n/2 ?runtime 0.029
#include<map>
#include<string>
#include<stdio.h>
#include<string.h>


using namespace std;


map<int ,int>mark;
int num[30];
char str[1100];


int bitcount(int x)
{
? ?return x == 0 ? 0 : bitcount(x / 2) + (x & 1);
}?


int main ()
{
? ?int n ,i ,j ,now ,l;
? ?while(~scanf("%d" ,&n))
? ?{
? ? ? for(i = 1 ;i <= n ;i ++)
? ? ? {
? ? ? ? ?scanf("%s" ,str);
? ? ? ? ?now = 0 ,l = strlen(str) - 1;
? ? ? ? ?for(j = 0 ;j <= l ;j ++)
? ? ? ? ?now = now ^ (1 << (str[j] - 'A'));
? ? ? ? ?num[i] = now;
? ? ? }
? ? ? mark.clear();
? ? ? int n1 = n / 2;
? ? ? int n2 = n - n1;
? ? ? for(i = 0 ;i < (1 << n1) ;i ++)
? ? ? {
? ? ? ? ?int x = 0;
? ? ? ? ?for(j = 1 ;j <= n1 ;j ++)
? ? ? ? ?if(i & (1 << (j-1))) x ^= num[j];
? ? ? ? ?if(!mark.count(x) || bitcount(i) > bitcount(mark[x]))
? ? ? ? ?mark[x] = i;
? ? ? }
? ? ? int Ans = 0;
? ? ? for(i = 0 ;i < (1<<n2) ;i ++)
? ? ? {
? ? ? ? ?int x = 0;
? ? ? ? ?for(j = 1 ;j <= n2 ;j ++)
? ? ? ? ?if(i & (1 << (j-1))) x ^= num[n1 + j];
? ? ? ? ?if(mark.count(x) && bitcount(i) + bitcount(mark[x]) > bitcount(Ans))
? ? ? ? ?Ans = (i << n1) ^ mark[x];
? ? ? }
? ? ? printf("%d\n" ,bitcount(Ans));
? ? ? int mk = 0,Anszt = Ans ,nowid = 1;
? ? ? while(Anszt)
? ? ? {
? ? ? ? ?if(Anszt&1)?
? ? ? ? ?{
? ? ? ? ? ? if(mk) printf(" %d" ,nowid);
? ? ? ? ? ? else printf("%d" ,nowid);
? ? ? ? ? ? mk = 1;
? ? ? ? ?}
? ? ? ? ?Anszt /= 2;
? ? ? ? ?nowid ++;
? ? ? }
? ? ? printf("\n");
? ? ??
? ? ? ? ?
? ?}
? ?return 0;
}
? ? ??
? ? ? ? ?
? ? ??

總結

以上是生活随笔為你收集整理的LA2965侏罗纪(异或和为0的最大数字个数)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。