2018.12.08【NOIP提高組】模擬B組 JZOJ 3518 進化序列
阿新 • • 發佈:2018-12-13
描述
有 這 個基因
一個基因
可以進化為序列中在它之後的基因
這個進化的複雜度,等於
的值
求進化後值小於 的方案數
思路
先扯淡
考試的時候就推出了
的優秀做法,真不知道寫題解的人是怎麼想的,竟然打線段樹。。。開氧氣後還比我快
正題
先把題解中的話引出來
說實話我考場都A了還沒看懂題解,寫的什麼鬼
個人做法:
我們發現若
能合併到
那麼顯然
也能合併到
,根據這個特性,我們用一個佇列維護一端可以被合併的值,入隊和出對操作的判斷要用位運算
時間複雜度:
暴力程式碼
#include<cstdio>
#include<cctype>
#include<algorithm>
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
#define r(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;int n,a[100001],yh[5001][5001],m,ans;
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline int read()
{
char c;int d=1,f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)write(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
signed main()
{
freopen("1.txt","r",stdin);
freopen("jhxl.txt","w",stdout);
n=read();m=read();
r(i,1,n) yh[i][i]=a[i]=read();
r(i,1,n-1) r(j,i+1,n) {yh[i][j]=yh[i][j-1]|a[j];if(yh[i][j]<m) ans++;}
write(ans);
}
正解
#include<cstdio>
#include<cctype>
#include<algorithm>
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
#define r(i,a,b) for(register int i=a;i<=b;i++)
#define getk r(j,0,30) if(now[j]) k|=1<<j
using namespace std;int n,a[100001],m,head,now[32],k;
long long ans;
inline char Getchar()
{
static char buf[100000],*p1=buf+100000,*pend=buf+100000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,100000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline int read()
{
char c;int d=1,f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)write(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
signed main()
{
freopen("1.txt","r",stdin);
freopen("jhxl2.txt","w",stdout);
n=read();m=read();
r(i,1,n) a[i]=read();
r(i,0,30) if((a[1]>>i)&1) now[i]++;
head=1;
r(i,2,n)
{
r(j,0,30) if((a[i]>>j)&1) now[j]++;//放入對尾
k=0;
getk;
while(k>=m&&head<i)//不滿足要求剔除對頭
{
r(j,0,30) if((a[head]>>j)&1) now[j]--;
k=0;
getk;
head++;
}
ans+=i-head;//加上方案
}
write(ans);
}
Rand生成
#include<cstdlib>
#include<cstdio>
#include<ctime>
using namespace std;
signed main()
{
freopen("1.txt","w",stdout);
srand(time(0));
printf("5000 %d\n",1+rand()%10000);
for(register int i=1;i<=5000;i++) printf("%d ",1+rand()%10000);
}
d(對)p(拍)
#include<cstdlib>
#include<cstdio>
#include<ctime>
using namespace std;double t1,t2,t3;
signed main()
{
for(register int i=1;i<1001;i++)
{
system("rand.exe");
t1=clock();
system("jhxl.exe");
t2=clock();
system("jhxl2.exe");
t3=clock();
if(system("fc jhxl.txt jhxl2.txt"))
{printf("測試點:#%3d 測試點資訊:WA",i);return 0;}
else printf("測試點:#%3d 測試點資訊:AC n方用時:%0.3lfms nlogn用時:%0.3lfms\n",i,t2-t1,t3-t2);
}
}