0
点赞
收藏
分享

微信扫一扫

AtCoder Regular Contest 066 好题


 

C - Lining Up

Time Limit: 2 sec / Memory Limit: 256 MB

Score : 300300 points

Problem Statement

There are NN people, conveniently numbered 11 through NN. They were standing in a row yesterday, but now they are unsure of the order in which they were standing. However, each person remembered the following fact: the absolute difference of the number of the people who were standing to the left of that person, and the number of the people who were standing to the right of that person. According to their reports, the difference above for person ii is AiAi.

Based on these reports, find the number of the possible orders in which they were standing. Since it can be extremely large, print the answer modulo 109+7109+7. Note that the reports may be incorrect and thus there may be no consistent order. In such a case, print 00.

Constraints

  • 1≦N≦1051≦N≦105
  • 0≦Ai≦N−10≦Ai≦N−1

Input

The input is given from Standard Input in the following format:


NN A1A1 A2A2 ...... ANAN


Output

Print the number of the possible orders in which they were standing, modulo 109+7109+7.

Sample Input 1 Copy

Copy


5 2 4 4 0 2


Sample Output 1 Copy

Copy


4


There are four possible orders, as follows:

  • 2,1,4,5,32,1,4,5,3
  • 2,5,4,1,32,5,4,1,3
  • 3,1,4,5,23,1,4,5,2
  • 3,5,4,1,23,5,4,1,2

Sample Input 2 Copy

Copy


7 6 4 0 2 4 0 2


Sample Output 2 Copy

Copy


0


Any order would be inconsistent with the reports, thus the answer is 00.

Sample Input 3 Copy

Copy


8 7 5 1 1 7 3 5 3


Sample Output 3 Copy

Copy


16


题意:

n个数据,a[i]表示前面的人数和后面的人数的差值。求排列方式。

分析:

写几个样例就出来了

n=5

 4 2 0 2 4

n=7

  6 4 2 0 2 4 6

n=6

5 3 1 1 3 5

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 100005;
const int mod = 1e9+7;
int a[N];
int num[N];
ll qpow(ll a,ll b,ll p)
{
ll ans=1%p;
while(b)
{
if(b&1) ans=(ans*a)%p;
b>>=1;
a=(a*a)%p;
}
return ans;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
num[a[i]]++;
}
if(n%2==1)
{
int flag=1;
for(int i=n-1;i>=0;i-=2)
{

if(i==0)
{
if(num[i]!=1)
{
flag=0;
break;
}
}
else
{
if(num[i]!=2)
{
flag=0;
break;
}
}
}
if(flag==0) printf("0\n");
else
{
ll ans=qpow(2,n/2,mod)%mod;
printf("%lld\n",ans);
}
}
else
{
int flag=1;
for(int i=n-1;i>=1;i-=2)
{

if(num[i]!=2)
{
flag=0;
break;
}
}
if(flag==0) printf("0\n");
else
{
ll ans=qpow(2,n/2,mod)%mod;
printf("%lld\n",ans);
}
}
return 0;
}

D - Xor Sum

Time Limit: 2 sec / Memory Limit: 256 MB

Score : 600600 points

Problem Statement

You are given a positive integer NN. Find the number of the pairs of integers uu and vv (0≦u,v≦N)(0≦u,v≦N) such that there exist two non-negative integers aa and bbsatisfying aa xorxor b=ub=u and a+b=va+b=v. Here, xorxor denotes the bitwise exclusive OR. Since it can be extremely large, compute the answer modulo 109+7109+7.

Constraints

  • 1≦N≦10181≦N≦1018

Input

The input is given from Standard Input in the following format:


NN


Output

Print the number of the possible pairs of integers uu and vv, modulo 109+7109+7.

Sample Input 1 Copy

Copy


3


Sample Output 1 Copy

Copy


5


The five possible pairs of uu and vv are:

  • u=0,v=0u=0,v=0 (Let a=0,b=0a=0,b=0, then 00 xorxor 0=00=0, 0+0=00+0=0.)
  • u=0,v=2u=0,v=2 (Let a=1,b=1a=1,b=1, then 11 xorxor 1=01=0, 1+1=21+1=2.)
  • u=1,v=1u=1,v=1 (Let a=1,b=0a=1,b=0, then 11 xorxor 0=10=1, 1+0=11+0=1.)
  • u=2,v=2u=2,v=2 (Let a=2,b=0a=2,b=0, then 22 xorxor 0=20=2, 2+0=22+0=2.)
  • u=3,v=3u=3,v=3 (Let a=3,b=0a=3,b=0, then 33 xorxor 0=30=3, 3+0=33+0=3.)

Sample Input 2 Copy

Copy


1422


Sample Output 2 Copy

Copy


52277


Sample Input 3 Copy

Copy


1000000000000000000


Sample Output 3 Copy

Copy


787014179


题意:

给你个数n,找出多少对<u,v>,0<=u,v<=n满足u=a xor b,v=x + b。

分析:

我们知道 a xor b <= a + b (a xor b == a + b 时当且仅当 a & b = 0),所以我们只要保证a+b<=n即可,则题意就转化为找出多少对a,b,满足a+b<=n。

避免重复:a>=b 

我们设dp[0]=1 表示a=0,b=0;

           dp[1]=2,表示a=1,b=0或a=0,b=0;

我们讨论正推过程:

一个数n在由小数向大数递推的过程中总共有三种情况(考虑除法的向下取整):

1.(n/2 + n/2 ),

2.(n/2+1 + n/2)

3.(n/2+1, n/2+1)

三种情况有时候加起来<=n但是绝不能让他们出现大于n的情况。

这里就可以写递推式了:dp[n]=dp[n/2]+dp[(n-1)/2]+dp[(n-2)/2](待理解)

 

dp[0] :(0,0) dp[1] :(0,0) (1,0) 例如:dp[2] = dp[1]+dp[0]+dp[0] dp[1]进行(n*2,n*2)操作 (0,0) (2,0) dp[0]进行 (n*2+1,n*2)操作 (1,0) dp[0]进行 (n*2+1,n*2+1)操作 (1,1), dp[2] = 4 (0,0)(1,0)(1,1)(2,0)

 

dp[3] = dp[1]+dp[1]+dp[0] dp[1]进行(n*2,n*2)操作 (0,0) (2,0) dp[1]进行(n*2+1,n*2操作 (1,0) (3,0) dp[0]进行(n*2+1,n*2+1)操作 (1,1)

 

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 100005;
const int mod = 1e9+7;
int a[N];
map<ll,ll>dp;
ll f(ll x)
{
if(dp[x]!=0) //记忆化
return dp[x];
else
return dp[x]=(f(x/2)%mod+f((x-1)/2)%mod+f((x-2)/2)%mod)%mod;
}
int main()
{
ll n;
scanf("%lld",&n);
dp[0]=1;
dp[1]=2;
cout<<f(n);
return 0;
}

 

举报

相关推荐

0 条评论