zoukankan      html  css  js  c++  java
  • ACM Training DAY 1

    https://vjudge.net/contest/321593
    今天打了2018CCPC的网络赛,整个人毫无状态,极其颓废。

    接下来按照题目难度顺序整理(学习):
    D Find Integer
    给出a和n,求使(a^n+b^n=c^n)成立的b和c,无解则输出-1 -1

    虽说是裸的费马定理的板子,但是我真的不知道啊……
    费马定理: (n>2)时,(a^n+b^n=c^n)无解
    (n=1)时,(a+b=c),固输一个1和1+a即可
    (n=2)时,(a^2+b^2=c^2),勾股数:
    (a)为奇数时,(tmp=a/2;) (b=(tmp+1)*tmp*2;) (c=b+1;)
    (a)为偶数时,(tmp=a/2-1;) (b=(tmp+2)*tmp;) (c=b+2;)

    所以总之,这就是个特判固输题,但是……

    #include<cstdio>
    typedef long long ll;
    using namespace std;
    ll t,n,a,b,c,tmp;
    
    int main()
    {
    	scanf("%lld",&t);
    	while (t--)
    	{
    		scanf("%lld%lld",&n,&a);
    		if (n==1) printf("1 %lld
    ",a+1);
    		else if (n>2 || n==0) printf("-1 -1
    ");
    		else
    		{
    			if (a&1)
    			{
    				tmp=a/2;
    				b=(tmp+1)*tmp*2;
    				c=b+1;
    			}
    			else
    			{
    				tmp=a/2-1;
    				b=(tmp+2)*tmp;
    				c=b+2;
    			}
    			printf("%lld %lld
    ",b,c);
    		}
    	}
    	return 0;
    }
    

    I Tree and Permutation
    给出一个点数为n的树,求1~n的所有全排列对应到树上相应位置后,从1-2-...-n经过的边权的和

    初步思路没有问题,求一条边两端分别有多少点,但是对于次数的计算不太明了。
    事实上,如果这条边的一端为(M)个点,另一端为(N-M)个点,则经过他的次数就是(M*(N-M)),再算上不同的全排列:这两个点有(N-1)种,除了这两个点以外有((N-2)!)种,所以这条边造成的贡献就总共有(L*M*(N-M)*(N-1)!),其中(L)为该边的边长
    那么每条边的贡献出来了之后,我们只要dfs求端点个数,在过程中求出答案就可以了

    #include<cstdio>
    #include<cstring>
    #define N 100010
    #define P 1000000007
    typedef long long ll;
    using namespace std;
    int n,head[N],cnt,son[N];
    ll sum;
    struct hhh
    {
    	int nxt,to,w;
    }e[N*2];
    
    void add(int x,int y,int z)
    {
    	e[cnt].nxt=head[x];
    	e[cnt].to=y;
    	e[cnt].w=z;
    	head[x]=cnt++;
    }
    
    void dfs(int x,int f)
    {
    	for (int i=head[x],v;i;i=e[i].nxt)
    	{
    		v=e[i].to;
    		if (v==f) continue;
    		dfs(v,x);
    		sum+=1LL*2*son[v]*(n-son[v])%P*e[i].w%P;
    		sum%=P;
    		son[x]+=son[v];
    	}
    	son[x]++;
    }
    
    ll get(ll x)
    {
    	ll s=1;
    	for (int i=2;i<=x;i++)
    		s=s*i%P;
    	return s;
    }
    
    int main()
    {
    	while (~scanf("%d",&n))
    	{
    		memset(head,0,sizeof(head));
    		memset(son,0,sizeof(son));
    		cnt=1;
    		sum=0;
    		for (int i=1,x,y,z;i<n;i++)
    		{
    			scanf("%d%d%d",&x,&y,&z);
    			add(x,y,z);
    			add(y,x,z); 
    		}
    		dfs(1,0);
    		(sum*=get(n-1))%=P;
    		printf("%lld
    ",sum);
    	}
    	return 0;
    } 
    

    C Dream
    要求重定义+和*,使得((m+n)^p=m^p+n^p)且存在(q<p)使得({q^k | 0<k<p,k in Z} = {k | 0<k<p , k in Z})
    其中p是质数。

    因为p是质数,考虑费马小定理,((m+n)^{p-1} equiv 1 (mod p)),所以((m+n)^p equiv m+n (mod p))
    同样的,(m^p=m)(n^p=n),所以(m^p+n^p=m+n),所以((m+n)^p=m^p+n^p)可得。
    综上,重定义的+和就是在(mod p)意义下的+和

    (这怎么想到费马小定理嘛……

    #include<cstdio>
    using namespace std;
    int t,p;
    
    int main()
    {
    	scanf("%d",&t);
    	while (t--)
    	{
    		scanf("%d",&p);
    		for (int i=0;i<p;i++)
    			for (int j=0;j<p;j++)
    				printf("%d%c",(i+j)%p," 
    "[j==p-1]);
    		for (int i=0;i<p;i++)
    			for (int j=0;j<p;j++)
    				printf("%d%c",i*j%p," 
    "[j==p-1]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    LR三:post接口_ajax上传
    LR二:post接口_form表单上传
    Dijkstra优先队列优化
    Misha and Changing Handles
    HDU-1428(记忆化搜索)
    CF-599B
    POJ-1488(字符串应用)
    New Year Permutation(Floyd+并查集)
    HDU-1078
    HDU-5532(LIS-nlogn)
  • 原文地址:https://www.cnblogs.com/mrha/p/13678529.html
Copyright © 2011-2022 走看看