第十六届浙江省大学生程序设计竞赛

目录

 

B Element Swapping

E Sequence in the Pocket

F Abbreviation

G Lucky 7 in the Pocket

H Singing Everywhere

I Fibonacci in the Pocket

J Welcome Party

K Strings in the Pocket


B Element Swapping

【题意】已知交换前数列的x,y,该数列某两个位置互换后得到给定数列,根据x,y计算现数列由原序列交换位置的方案数。

【解题思路】推公式题。将原序列的x,y值设为x1,y1,现序列的x,y值设为x2,y2,设互换了p,q两个位置,易得以下两个等式dx=x2-x1=(p-q)(ap-aq)与dy=y2-y1=(p-q)(ap^2-aq^2),两式联立后易得dy=dx*(ap+aq),所以遍历一遍数组,对于每个树都能得到一个可以与她交换的数,再判断一下是否成立即可。对啦dx==0 &&dy==0的情况是只要数列中相同的数交换都可以,记得一定要特判,不然一直浮点错误。

【代码】

#include
using namespace std;
const int maxn=1e5+100;
typedef long long LL;
LL a[maxn],tot[maxn],c[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        LL x1=0,y1=0,x2=0,y2=0,ans=0;
        memset(tot,0,sizeof(tot));
        scanf("%d%lld%lld",&n,&x1,&y1);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            tot[a[i]]++;
            x2+=1LL*i*a[i];
            y2+=1LL*i*a[i]*a[i];
        }
        LL dx=x2-x1,dy=y2-y1;
        if(dx==0 && dy==0)
        {
            for(int i=1;i<=100000;i++)
            {
                if(tot[i]>1)
                    ans+=(tot[i]*(tot[i]-1))/2LL;
            }
        }
        else if(dx!=0 && dy!=0)
        {
            if(dy%dx==0)
            {
                LL p=dy/dx;
                for(int i=1;i<=n;i++)
                {
                    if(a[i]i&& q<=n&&a[q]==p-a[i])ans++;
                        }
                    }
                }
            }
        }
        printf("%lld\n",ans);
    }
}

E Sequence in the Pocket

【题意】给一个长度为n的数组,每次操作可以把一个数放到最前面,问最少几次操作可以使这个数组变成非递减数列。

【解题思路】签到题,排序后倒序查找即可。

【代码】

#include
using namespace std;
const int maxn=1e5+5;
int a[maxn],b[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int cnt=0,n;
        scanf("%d",&n);
        for(int i=0;i=0;i--)
        {
            if(a[i]==b[t])
            {
                t--;
                cnt++;
            }
        }
        printf("%d\n",n-cnt);
    }
}

F Abbreviation

【题意】除单词的首字母外,去除原因字母。

【解题思路】签到题。

【代码】

#include
using namespace std;
const int maxn=1e5+5;
char a[maxn],b[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        string s1,s2;
        cin>>s1;
        s2=s1[0];
        for(int i=1;i

G Lucky 7 in the Pocket

【题意】找一个大于等于n的,能被7整除但不能被4整除的最小整数。n<=100。

【解题思路】签到题。

【代码】

#include
using namespace std;
const int maxn=1e5+5;
char a[maxn],b[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=n;i<=500;i++)
        {
            if(i%7==0 && i%4!=0)
            {
                printf("%d\n",i);
                break;
            }
        }
    }
}

H Singing Everywhere

【题意】给n个数,最多可以删去一个数使这个数列中的峰值出现次数最少。

【解题思路】签到题。先把峰值位置都找出来,分类讨论一下即可。

(1)当峰值位置只相隔1个位置时,且两个峰值一样大时,删去中间那个数达到最优,ans-2。

(2)其余只要判断一下前后的大小关系,最多只可能-1。

【代码】

#include
using namespace std;
const int maxn=1e5+5;
long long a[maxn],b[maxn];
vectorv;
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        v.clear();
        scanf("%d",&n);
        for(int i=0;ia[i-1] && a[i]>a[i+1])v.push_back(i);
        }
        int ans=v.size(),f=0;
        if(v.size()>=1)
        {
            for(int i=0;it3)
                    {
                        if(v[i]-2>=0)
                        {
                            int t0=a[v[i]-2];
                            if(t0

I Fibonacci in the Pocket

【题意】求斐波那契数列的第a到第b项和为奇数还是偶数。

【解题思路】签到题。因为斐波那契数列的特征是奇 奇 偶 奇 奇 偶……即3的倍数即为偶数,所以只需要判断a和b被3除的情况即可。不需要大数,只需要将该数的每一位加起来除3即可。

【代码】

#include
using namespace std;
const int maxn=1e5+5;
char a[maxn],b[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s",a,b);
        int suma=0,sumb=0,la=strlen(a),lb=strlen(b);
        for(int i=0;i

J Welcome Party

【题意】有n个人,m对朋友,如果某个人的一个朋友已经进去了,那么他就不会不开心,如果里面一个朋友都没有,他就会不开心,求最少的不开心人数以及进入的最小序列(然而比赛的时候读成一个人只有当它的所有朋友进去了他才会开心……)。

【解题思路】并查集找一下连通块,连通块个数即为答案,再用优先队列维护一下即可输出最小序列。(坑点是卡时间……)

【代码】

#include
using namespace std;
const int maxn=1e6+5;
int pre[maxn],vis[maxn],n,m,ans,ans1[maxn],tot;
vectorv[maxn];

int findroot(int x)
{
    return pre[x]==x?x:pre[x]=findroot(pre[x]);
}
void bfs()
{
    priority_queue,greater >pq;
    for(int i=1;i<=n;i++)
    {
        if(pre[i]==i)
        {
            ans++;
            pq.push(i);
            vis[i]=1;
        }
    }
    while(!pq.empty())
    {
        int t=pq.top();
        pq.pop();
        ans1[tot++]=t;
        for(int i=0;i

K Strings in the Pocket

【题意】给一个字符串s和t,询问s的子串翻转后得到t的方案数。

【解题思路】当s和t相等时,需要用马拉车算法,马拉车算法用于求字符串的回文串,p[i]表示以位置i为中心的回文串的长度;当s和t不相等时,设置指针l和r,分别找到第一个s字符串和t字符串中s[l]和t[l]、s[r]和t[r]不等的位置,然后一直往外扩即可。

【代码】

#include
using namespace std;
typedef long long LL;
const int maxn=2e6+5;
LL p[maxn*2];
LL ans;
int len;
char s[maxn],tmp[maxn*2],t[maxn];
/*
void init()
{
    int len=2;
    ts[0]='$';
    ts[1]='#';
    for(int i=0;i=0 && r

 

你可能感兴趣的:(题目整理)