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;
}