zoukankan      html  css  js  c++  java
  • 11.5NOIP2018提高组模拟题

    书信(letter)

    Description

    有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信。 显然, 这样一共有 n!种拿到书信的情况。

    现在亮亮规定, 对任意的 1<=x,y<=n, 如果 x 号小朋友拿到 u 号小朋友写的 书信, y 号小朋友拿到 v 号小朋友写的书信, 那么(x+y)号小朋友必须拿到(u+v) 号小朋友写的书信(这里的加法若和超过了 n, 那么就减去 n) 。

    小林想知道, 总共有多少种拿到书信的情况呢?

    Input

    只有一行一个正整数 n。

    Output

    只有一行一个正整数, 表示符合条件的情况的总数。

    这题感觉不太可证明,自己不会

    通过枚举全排列打表发现,这题就是一个裸的求(phi(n))

    (O(sqrt{n}))(phi(n))的话就不多(BB)了 。

    这里放一下公式。

    [phi(x)=x imes prod_{i=1}^{r} (1-frac{1}{p_i}) ]

    然后直接去求然后输出即可。

    代码

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define int long long 
    #define R register
    
    using namespace std;
    
    inline void in(R int &x)
    {
    	int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    
    int n;
    
    inline int phi(int x)
    {
        int res=x;
        for(int i=2;i*i<=x;i++)
        {
            if(x%i==0)
            {
                res=res/i*(i-1);
                while(x%i==0)x/=i;
            }
        }
        if(x>1)res=res/x*(x-1);
        return res;
    }
    
    
    signed main()
    {
    	freopen("letter.in","r",stdin);
    	freopen("letter.out","w",stdout);
    	
    	in(n);
    	printf("%lld
    ",phi(n));
    
    	fclose(stdin);
    	fclose(stdout);
    	
    	return 0;
    }
    

    金条(au)

    Description

    小林在一家商店里购物, 共有 i 件物品, 第 i 件物品的价格为 i。 小林身上带 了许多金条, 每根金条的价值都为整数, 价值为 1~N 的金条数量都足够多。

    对于任何一件物品,小林只会用同一价值的若干金条购买它,而且不能找零。 因此, 对于第 i 件物品, 会有 C(i)种购买方法。 小林只会选择这样的一件物品 i 进行购买: C(i) > max{ C(j) }, 1 <= j < i。

    请你告诉小林, 他能购买的最贵的物品的价格是多少。

    Input

    只有一行一个整数 N。

    Output

    只有一个整数, 表示答案。

    通过读题可以发现,我们是求(1)(n)之间的约数个数最多的数。

    PS:如果两个数的约数个数相同,取较小的一个。

    有一个结论:可以求一个数的约数个数。

    首先根据唯一分解定理(其中(p_1)是素数)

    [x=p_1^{k_1} imes p_2^{k_2} imes p_3^{k_3} imes dots ]

    那么一个数的约数个数就是这个:

    [d(x)=(k_1+1) imes(k_2+1) imes dots ]

    (d(x))表示(x)的约数个数。

    然后通过计算可以知道,在(2 imes 10^9)中不同的质数的个数不会超过(10)个.

    因此我们写出前(10)个素数.

    然后直接暴力搜索即可。

    注意:两个数的约数个数相同的话,取较小的一个。

    题目要求严格(>)

    代码

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define int long long
    #define R register
    
    using namespace std;
    
    inline void in(int &x)
    {
    	int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    int prime[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41};
    int ans,mx,n;
    void dfs(R int dep,R int now,R int cnt)
    {
    	if(dep>=11)return;		
    	if(cnt>mx)mx=cnt,ans=now;
    	if(cnt==mx and ans>now)ans=now;
    	for(R int i=1;i<=32;i++)
    	{
    		if(now*prime[dep]>n)break;
    		dfs(dep+1,now*=prime[dep],cnt*(i+1));
    	}
    }
    signed main()
    {
    	freopen("au.in","r",stdin);
    	freopen("au.out","w",stdout);
    	
    	in(n);
    	dfs(1,1,1);
    	printf("%lld",ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	
    	return 0;
    }
    

    小朋友(friend)

    Description

    n 个小朋友在一起做游戏, 第 i 个小朋友的快乐值为 Di。 当第 i 个小朋友和 第 j 个小朋友一起玩时, 他们能获得 Di xor Dj 的快乐值。 每一个小朋友 i 都 想知道, 他和谁一起玩能够获得最大的快乐值, 请你帮他们每个人分别求出这个 值。

    Input

    第一行有一个整数 (n)。 第二行三个整数 (K, B, P)(1≤K≤20)(0≤B<2^{16})(0≤P<2^{24})) 。 根据 $ D_i = (K imes D_{i-1} + B)%2^{24}$ 和 (D_1 = P) 自行计算整个 (P) 数组 。

    Output

    一个整数 (Ans)(Ans=(sum_{i=1}^{n} 3^{i-1} imes Ans_i)%2^{24}) 。 其中 (Ans_i) 表示对于第 i 个小朋友 我们需要的答案。

    表示看到异或,还是取两两异或的最大值,选择树(01Trie)

    这个东西网上讲解很多,不多(BB).

    我们将得到的(D_i)插入到(Trie)树中。

    查询就普通查询(贪心)即可。

    时限由于有(5s)所以怎么搞都行。

    注意不要傻到每次(ksm)(3^{i-1})

    可以预处理,可以用一个变量。(这里我用了预处理)

    这可以说是一个裸题?

    代码

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define mod 16777216
    #define lo long long 
    #define R register
    
    using namespace std;
    
    const int gz=2e6+5;
    
    inline void in(R lo &x)
    {
    	int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    
    lo n,K,B,P,ans;
    lo a[gz],po[gz]={1};
    
    struct Trie
    {
    	int ch[gz*15][2],idx;
    	
    	inline void ins(R int x)
    	{
    		R int u=0;
    		for(R int i=25;i>=0;i--)
    		{
    			R int bit=(x>>i)&1LL;
    			if(!ch[u][bit])ch[u][bit]=++idx;
    			u=ch[u][bit];
    		}
    	}
    	inline int query(R int x)
    	{
    		R int u=0,res=0;
    		for(R int i=25;i>=0;i--)
    		{
    			R int bit=(x>>i)&1LL;
    			if(ch[u][bit^1])
    			{
    				res+=(1LL<<i);
    				u=ch[u][bit^1];
    			}
    			else u=ch[u][bit];
    		}
    		return res;
    	}
    }woc;
    
    int main()
    {
    	freopen("friend.in","r",stdin);
    	freopen("friend.out","w",stdout);
    	
    	in(n);in(K),in(B),in(P);a[1]=P%mod;woc.ins(a[1]);
    	for(R int i=1;i<=n;i++)po[i]=po[i-1]*3%mod;
    	for(R int i=2;i<=n;i++)
    	{
    		a[i]=((K*a[i-1])%mod+B)%mod;
    		woc.ins(a[i]%mod);
    	}
    	for(R int i=1;i<=n;i++)
    		(ans+=po[i-1]*woc.query(a[i])%mod)%=mod;
    	printf("%lld
    ",(ans+mod)%mod);
    }
    
  • 相关阅读:
    围炉夜话(14)
    围炉夜话(13)
    ATmega128中应用的hex与bootloader的hex合并的实现
    配置IAR for AVR 既可以仿真也可以生成Hex文件
    atmega128 bootloader程序在IAR-AVR下 linker文件的配置及原因
    一步步学习SPD2010--第十四章节--在Web页面使用控件(8)--关键点
    一步步学习SPD2010--第十四章节--在Web页面使用控件(7)--使用SP服务器控件
    一步步学习SPD2010--第十四章节--在Web页面使用控件(6)--测试ASP.NET表单
    一步步学习SPD2010--第十四章节--在Web页面使用控件(4)--使用ASP.NET验证控件
    一步步学习SPD2010--第十四章节--在Web页面使用控件(3)--验证用户数据输入
  • 原文地址:https://www.cnblogs.com/-guz/p/9907944.html
Copyright © 2011-2022 走看看