·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)出解。

#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;
}
View Code

寻找(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(玄学但能过)的程序就出来了。

#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;
}
View Code

本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。

posted on 2017-10-02 10:33  Yzyet  阅读(214)  评论(0编辑  收藏  举报