[考试反思]0928csp-s模拟测试54:转瞬
Posted hzoi-deepinc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[考试反思]0928csp-s模拟测试54:转瞬相关的知识,希望对你有一定的参考价值。
咕了好久,也没什么想说的。
下一场就又爆炸了。。。
T3特判打丢一句话丢了14分,剩下其实都还好。
T1:
给我的第一感觉是建图找联通块,但既然只要找联通块为什么不直接并查集呢?
对于每一个数字合并它的所有因子,求出现过的因子形成几个联通块,特殊处理1。
二营长比我快了整整5分钟做出来的。
1 #include<cstdio> 2 #include<vector> 3 using namespace std; 4 #define mod 1000000007 5 #define int long long 6 vector<int>v[1000005]; 7 int x[100005],al[1000005],f[1000005],prime[1000005],cnt_prime;bool not_prime[1000005]; 8 int pow(int b,int t,int a=1)for(;t;t>>=1,b=b*b%mod)if(t&1)a=a*b%mod;return a; 9 int find(int k)return f[k]==k?k:f[k]=find(f[k]); 10 main() 11 int t;scanf("%lld",&t); 12 for(int i=2;i<=1000000;++i)if(!not_prime[i]) 13 prime[++cnt_prime]=i; 14 for(int j=i;j<=1000000;j+=i)v[j].push_back(i),not_prime[j]=1; 15 16 while(t--) 17 int n,cnt1=0;scanf("%lld",&n); 18 for(int i=1;i<=n;++i)scanf("%lld",&x[i]);if(x[i]==1)cnt1++; 19 for(int i=1;i<=cnt_prime;++i)f[prime[i]]=prime[i],al[prime[i]]=0; 20 for(int i=1;i<=n;++i)if(x[i]!=1)for(int j=1;j<v[x[i]].size();++j) 21 f[find(v[x[i]][j])]=find(v[x[i]][0]),al[v[x[i]][j]]=1;//,printf("%lld %lld\\n",v[x[i]][0],v[x[i]][j]); 22 for(int i=1;i<=n;++i)if(x[i]!=1)al[v[x[i]][0]]=1; 23 for(int i=1;i<=cnt_prime;++i)if(al[prime[i]])if(al[find(prime[i])]!=2) 24 al[find(prime[i])]=2,cnt1++; 25 printf("%lld\\n",(pow(2,cnt1)-2+mod)%mod); 26 27
思路积累:
- 埃筛:求出含有的每种质因子
- 并查集
T2:
莫名想到了双向搜索,因为20的范围会很卡但是折半之后就很好,然后就好做了。
可以发现我们要求的路径不限制终点。
那么分别处理以1为起点所能形成的长度为d/2的路径集合和以任意点为起点的路径集合。
然后把两种路径的终点接起来就形成了长度为d的路径。
比脸快23s抢到迷之首杀。
1 #include<cstdio> 2 int can[11][99][1028],n,fir[99],l[20000],to[20000],v[20000],cnt,m,d,rev[1028],ans,can2[11][99][1028],al[1048577]; 3 void link(int a,int b,int V)l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;v[cnt]=V; 4 int main() 5 scanf("%d%d%d",&n,&m,&d); 6 for(int i=1,a,b,V;i<=m;++i)scanf("%d%d%d",&a,&b,&V),link(a,b,V),link(b,a,V); 7 int lh=d>>1,rh=d-lh,usf=(1<<rh)-1; 8 can[0][1][0]=1;for(int i=1;i<=n;++i)can2[0][i][0]=1; 9 for(int len=0,L=1;len<lh;++len,++L)for(int i=1;i<=n;++i)for(int st=0;st<1<<len;++st)if(can[len][i][st]) 10 for(int j=fir[i];j;j=l[j])can[L][to[j]][st<<1|v[j]]=1; 11 for(int len=0,L=1;len<rh;++len,++L)for(int i=1;i<=n;++i)for(int st=0;st<1<<len;++st)if(can2[len][i][st]) 12 for(int j=fir[i];j;j=l[j])can2[L][to[j]][st<<1|v[j]]=1; 13 for(int i=0;i<1<<lh;++i)for(int j=1;j<=n;++j)if(can[lh][j][i]) 14 for(int k=0;k<=usf;++k)if(!al[i<<rh|k]&&can2[rh][j][k])al[i<<rh|k]=1,ans++; 15 printf("%d\\n",ans); 16
思路积累:
- 双向搜索:状态数开根
T3:
31分给暴力了。
+14分单调:只要处理第一个和最后一个就行。x[2]=x[n],n=2;然而考场上没写n=2,T掉了。。。
+20分曲折:二分最早的不能覆盖的段然后就是一次函数。
100分:大模拟。考场上有链表+堆的思路。感觉很不好打就没有打。
事实上的确很不好打,现在还没有A。
思路和下发的std不太一样。
以上是关于[考试反思]0928csp-s模拟测试54:转瞬的主要内容,如果未能解决你的问题,请参考以下文章