618模拟赛

T1

过于沙雕,直接跳过

T2

有一棵二叉树,我们定义如下:
每个结点都有两个孩子:左孩子与右孩子;
如果结点的值为整数 X,那么左孩子的值为 2X,右孩子的值为 2X+1;
根的值定义为 1。
现在,小 Y 同学在这棵二叉树上模拟步行。步行时由大写字母 L,R,P 来描述:
字母 L 表示走到左孩子上;
字母 R 表示走到右孩子上;
字母 P 表示停留。
步行结束时所在的结点的值即是步行的值,例如:LRP 的值是 5,RPP 的值是 3。
步行过程用一段包含字符 L,R,P 和的串表示,则可以表示三种移动的任意一种。
我们可以把分裂出的3个点整体考虑
也就是说L是总值
2,R总值2+1,而则是*5+当前个数

#include<bits/stdc++.h>
using namespace std;
inline long long read()
{
    long long tot=0,fs=1;
    char ch;
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') ch=getchar(),fs=-1;
    while(ch>='0'&&ch<='9') tot=tot*10+ch-'0',ch=getchar();
    return tot*fs;  
}
char s[10009];
int lens=1;
int len=1;
int cnt[100009],lencnt=1;
int num[100009];
int main ()
{
    scanf("%s",s);
    num[1]=1;
    cnt[1]=1;
    lens=strlen(s);
    for(int i=0;i<lens;i++)
    {
        if(s[i]=='L')
        {
            for(int i=1;i<=len;i++)
            {
                num[i]*=2;  
            }
            for(int i=1;i<=len;i++)
            {
                if(num[i]>9)
                {   
                    num[i+1]+=num[i]/10;
                    num[i]%=10; 
                }
                while(num[len+1]!=0) len++;
            }
        }
        if(s[i]=='R')
        {
            for(int i=1;i<=len;i++)
            {
                num[i]*=2;  
            }
            for(int i=1;i<=lencnt;i++)
            {
                num[i]+=cnt[i]; 
            }
            for(int i=1;i<=len;i++)
            {
                if(num[i]>9)
                {   
                    num[i+1]+=num[i]/10;
                    num[i]%=10; 
                }
                while(num[len+1]!=0) len++;
            }   
        }
        if(s[i]=='*') 
        {
            for(int i=1;i<=len;i++)
            {
                num[i]*=5;  
            }
            for(int i=1;i<=lencnt;i++)
            {
                num[i]+=cnt[i]; 
            }
            for(int i=1;i<=len;i++)
            {
                if(num[i]>9)
                {   
                    num[i+1]+=num[i]/10;
                    num[i]%=10; 
                }
                while(num[len+1]!=0) len++;
            }   
            for(int i=1;i<=lencnt;i++)
            {
                cnt[i]*=3;  
            }
            for(int i=1;i<=lencnt;i++)
            {
                if(cnt[i]>9)
                {   
                    cnt[i+1]+=cnt[i]/10;
                    cnt[i]%=10; 
                }
                while(cnt[lencnt+1]!=0) lencnt++;
            }
        }
    }
    for(int i=len;i>=1;i--)
    {
        printf("%d",num[i]);
    }
    return 0;
}

T3

过于沙雕,直接跳过

T4

有 n 个正整数 x1~xn,初始时状态均为未选。
有 m 个操作,每个操作给定一个编号 i,将 xi 的选取状态取反。
每次操作后,你需要求出选取的数中有多少个互质的无序数对。

·f(i)表示GCD为i的数对个数

·g(i)表示GCD为i的倍数的数对个数

·s(i)表示为i的倍数的数的个数

则有g(i)=s(i)*(s(i)-1)/2
g(i)=sigama(f(d))(i|d)
莫比乌斯反演即可
那么修改怎么办呢?
修改影响s
s影响g
g影响f
去掉旧的加上新的即可

   #include<stdio.h>
#define ll long long
#define go(i,a,b) for(int i=a;i<=b;i++)
const int N=500003;
int n,m,a[N],I,x,d,Mob[N];
ll s[N],g[N],f[N],ans;bool get[N];
struct Sieve
{
    int prime[N],t;bool no[N];
    void Mobius_Sieve()
    {
        Mob[1]=1;
        go(i,2,500000){if(!no[i])Mob[prime[++t]=i]=-1;
        go(j,1,t){if(1ll*prime[j]*i>500000)break;
        Mob[i*prime[j]]=i%prime[j]?-Mob[i]:0;
        no[i*prime[j]]=1;if(i%prime[j]==0)break;}}
    }
}Tool;
int main()
{    
    Tool.Mobius_Sieve();
    scanf("%d%d",&n,&m);
    go(i,1,n)scanf("%d",a+i);
    while(m--)
    {
        scanf("%d",&I);x=a[I];
        d=(get[I]^=1)?1:-1;
        go(i,1,x)if(x%i==0&&i*i<=x)
        {
            s[i]+=d;if(i!=x/i)
            s[x/i]+=d;

            ans-=Mob[i]*g[i];if(i!=x/i)
            ans-=Mob[x/i]*g[x/i];

            g[i]=s[i]*(s[i]-1)/2;if(i!=x/i)
            g[x/i]=s[x/i]*(s[x/i]-1)/2;

            ans+=Mob[i]*g[i];if(i!=x/i)
            ans+=Mob[x/i]*g[x/i];
        }
        else if(i*i>x)break;
        printf("%lld\n",ans);
    }
    return 0;
}

  转载请注明: wenjing233的小站 618模拟赛

 上一篇
杂题精选 杂题精选
由于某些题目年代过于久远,代码不再附赠 Walk给定n个点m条单向边,边权为1每个点有一定的点权,点权在2^20以内若vali&valj=valj则i到j之间还有一条长度为1的单向边现在从1出发,求到各个点的距离,若无法到达则为-1
2019-06-30
下一篇 
USACO原题大赛 USACO原题大赛
T1有N个单词,每个单词长c个字,韵律为k,你要用这些单词作诗,每个诗句长度必须为len诗的某些句子必须是相同的韵脚这样的句子组不超过26个 很显然的是,我们只要做一次背包DP推出每种韵脚,长度为len的句子有几个然后快速幂统计一下答案就好