·NOIP模拟赛
消消乐(tet)
【题目描述】
有一个2n个数字排成一列,这个数列中由1..n中的数字组成,每个数字都恰好出现两次。每个回合可以交换相邻两个数字,交换以后如果有两个相同的数字相邻,那么将这两个数字消除,并将这两个数字的两端拼起来;如果拼接后的数列仍有相同的数字相邻,那么将引发连锁反应直到没有两个相同数字相邻。现在你想知道最少需要几个回合可以消除所有的数字。
【输入描述】
第一行输入一个n,表示数字范围。
接下来的2n行,每行一个数字,表示第i个位置的数字。
【输出描述】
第一行输出一个数,表示最少需要的回合数w。
接下来的w行,每行输出一个数m[i]。m[i]表示对于第i回合,你的操作为交换当前数列中的第m[i]个数和第(m[i]+1)个数。如果有多种方案,允许输出任意一种。
保证存在不超过10^6的答案。
【样例】
输入 | 输出 |
5 5 2 3 1 4 1 4 3 5 2 | 2 5 2 |
【数据范围】
对于 30% 的数据, n≤1000
对于 100% 的数据, 1≤n≤50000
-----------------------------------------------------------
这题似乎真的丧。
首先,先弄一个栈。
然后一个个存进去,如果发现有2个相同的数字,而且中间隔着其他数字,又无法消掉,此时,交换是必须的。
所以就可以这样统计。O(n)出解。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();} return num*t; } const int N=5e4+10,M=1e6+10; int n,cnt=0,tmp=0,ans[M],s[M],pos[N]; int main() { freopen("tet.in","r",stdin); freopen("tet.out","w",stdout); n=read(); for(int i=1;i<=(n<<1);i++){ int x=read();s[++tmp]=x; if(pos[x]){ int t=pos[x]; while(t!=tmp-1){ swap(s[t],s[t+1]); pos[s[t]]--;ans[++cnt]=t++; } tmp-=2;pos[x]=0; } else pos[x]=tmp; } printf("%d\n",cnt); for(int i=1;i<=cnt;i++)printf("%d\n",ans[i]); return 0; }
寻找(find)
【题目描述】
你有一个长度为n个由abc三个字母组成的字符串s,你现在想知道有多少三元组(i,j,k)满足:
1、 s[i]=’a’,s[j]=’b’,s[k]=’c’
2、 j^2=ik
请你求出满足条件的三元组的数量
【输入描述】
第一行为n,表示字符串长度
第二行为一个长度为n的字符串。
【输出描述】
输出一个数, 表示满足条件的三元组的数量。
【样例】
输入 | 输出 |
5 abccc | 1 |
【数据范围】
对于 30% 的数据, n≤500
对于 50% 的数据, n≤5000
对于 70% 的数据, n≤1e5
对于 100% 的数据, 1≤n≤5e5
------------------------------------------------------------------------
首先,需要知道n的质因数最多只有log2(n)(假设log2(n)=x,那么n=2^x)。为什么呢?
因为最小的质数是2,所以说一个数的质因数的总个数<=log2(n)。
很容易可以的到如果n有x个质因数,那么n^2有2x个质因数。
我们对于每一个合法的j,求它的质因数,把它每一个质因数个数都乘2,就是j^2的质因数了。
然后我们用dfs搜i,k。然后这个O(玄学但能过)的程序就出来了。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define ll long long using namespace std; int n;char c[500010]; int a[100][2],cnt,ans=0;ll tmp; void add(int x){ int t;cnt=0; for(int i=2;i*i<=x;i++) if(x%i==0){ t=0; while(x%i==0){t+=2;x/=i;} a[++cnt][0]=i;a[cnt][1]=t; } if(x>1)a[++cnt][0]=x,a[cnt][1]=2; } void dfs(int x,ll y){ if(x>cnt){ ll t=tmp*tmp*1ll/y; if(t<=n&&(c[y]=='a'&&c[t]=='c'||c[y]=='c'&&c[t]=='a'))ans++; return; } dfs(x+1,y); for(int i=1;i<=a[x][1];i++){ y*=a[x][0]; if(y>=tmp)break; dfs(x+1,y); } } int main() { freopen("find.in","r",stdin); freopen("find.out","w",stdout); scanf("%d",&n);scanf("%s",c+1); for(tmp=2;tmp<n;tmp++) if(c[tmp]=='b'){ add(tmp);dfs(0,1); } printf("%d",ans); return 0; }
本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。