1 64
Case #1: 0 Case #2: 19
题意:问2^m-1有几位...
思路:你会发现-1只有在 10的倍数时候位数才会发生变化 10-1 = 9, 100-1, 1000-1...2^m不可能出现这种数
,所以只考虑2^m有几位就好了...就是10的几次方, 取个log10, 答案就是m×log2;
代码:
#include
#include
#include
#include
#include
using namespace std;
int main()
{
int n, ca = 1;
while(~scanf("%d", &n))
{
int k = log10(2)*n;
printf("Case #%d: %d\n",ca++, k);
}
return 0;
}
1 a 2 aa bb 3 a ba abc
Case #1: 25 Case #2: 1323 Case #3: 18221
题意:给你n个由小写字母组成的字符串,让你给26个字母分配0-25,每个字符串形成一个26进制的数字,问怎么分
配权值这n个数的和最大。(不能有前导0,但是单个0可以)
官方题解:每个字符对答案的贡献都可以看作一个 26 进制的数字,问题相当于要给这些贡献加一个 0 到 25 的权重
使得答案最大。最大的数匹配 25,次大的数匹配 24,依次类推。排序后这样依次贪心即可,唯一注意的是不能出现
前导 0。关键就是排序,其实结构体排序可以按照数组字典序排序的
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e5+5;
ll fac[maxn] = {1};
int tmp[27];
int Hash[27];
bool lead[27];
char str[maxn];
void init()
{
for(int i = 1; i < maxn; i++)
fac[i] = fac[i-1]*26%mod;
}
struct node
{
int cnt[maxn];
int id;
bool operator < (const node &a) const
{
for(int i = maxn-1; i >= 0; i--)
{
if(cnt[i] > a.cnt[i]) return 1;
else if(cnt[i] < a.cnt[i]) return 0;
else ;
}
}
}a[27];
int main(void)
{
int n, ca = 1;
init();
while(~scanf("%d", &n))
{
memset(a, 0, sizeof(a));
memset(Hash, -1, sizeof(Hash));
memset(lead, 0, sizeof(lead));
int r = 0;
for(int i = 1; i <= n; i++)
{
scanf(" %s", str);
int len = strlen(str);
r = max(r, len-1);
if(len != 1)
lead[str[0]-'a'] = 1;
for(int i = 0; i < len; i++)
a[str[i]-'a'].cnt[len-i-1]++;
}
for(int i = 0; i < 26; i++)
{
for(int j = 0; j < maxn; j++)
{
if(a[i].cnt[j] >= 26)
{
a[i].cnt[j+1] += a[i].cnt[j]/26;
a[i].cnt[j] %= 26;
}
}
a[i].id = i;
}
sort(a, a+26);
// for(int i = 0; i < 26; i++)
// cout << a[i].id << endl;
for(int i = 0; i < 26; i++)
Hash[a[i].id] = 26-i-1;
for(int i = 0; i < 26; i++)
if(lead[a[i].id] && Hash[a[i].id] == 0)
{
for(int j = 25; j >= 0; j--)
{
if(!lead[a[j].id])
{
for(int k = 25; k >= j+1; k--)
Hash[a[k].id] = Hash[a[k-1].id];
Hash[a[j].id] = 0;
// swap(Hash[a[i].id], Hash[a[j].id]);
break;
}
}
break;
}
ll ans = 0;
// for(int i = 0; i < 26; i++)
// cout << Hash[i] << endl;
for(int i = 0; i < 26; i++)
{
for(int j = 0; j < maxn; j++)
{
ans = (ans+fac[j]*a[i].cnt[j]*Hash[a[i].id]%mod)%mod;
}
}
printf("Case #%d: %lld\n", ca++, ans);
}
return 0;
}
3 2 1 0 2 0 1 3 4 2 0 1 0 2 3 1
Case #1: 4 Case #2: 4
题目大意:
给你一个数组A,和一个数组B,数组A是【0~n-1】的排咧,数组B是【0~m-1】的排列。
现在定义F(i)=bF(ai);
问有多少种取值,使得F(i)全部合法。
样例1可行的解:
110
111
001
000
思路:
写出样例2的公式:
①F(0)=bF(2)
②F(1)=bF(0)
③F(2)=bF(1)
我们不难发现,如果我们设定了F(0)的值,就能够通过式子②能够得知F(1)的值,然后就能通过式子③得知F(2)的值,最后再回归式子①尝试当前设定的值是否合法了。
这就是一个循环节
我们对于A数组中的一个环的话如果一个环中的任意一个点的价值我们能够设定出来,那么这一个循环节的所有点的值就都能够知道了。
然而这个能够设定的值,肯定是数组B中的一个值,而且我们已知都是循环节,那么数组B中的这个被选中设定的值也一定存在一个循环节,而且这个循环节的长度,一定是A长度循环节的因子长度。
A数组中长度为D的一个循环节,如果B数组中有一个循环节的长度为d,并且如果D%d==0.那么这个B数组的这个循环节的所有值,都可以作为A数组中这个循环节的值。那么对于A数组中的这个循环节来讲,答案数就多了d个。
过程统计每个循环节能够满足的答案的个数,然后累乘即可。
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7;
const int Mod = 1e9 + 7;
int a[maxn], b[maxn], n, m, cnt1[maxn], cnt2[maxn], book[maxn];
int main()
{
int ca = 1;
while(~scanf("%d%d", &n, &m))
{
memset(cnt1, 0, sizeof(cnt1));
memset(cnt2, 0, sizeof(cnt2));
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
for(int i = 0; i < m; i++)
scanf("%d", &b[i]);
memset(book, 0, sizeof(book));
int tot = 0;
for(int i = 0; i < n; i++)
{
int index = i, cnt = 0;
while(!book[index])
{
cnt++;
book[index] = 1;
index = a[index];
}
if(cnt)
cnt1[tot++] = cnt;
}
memset(book, 0, sizeof(book));
for(int i = 0; i < m; i++)
{
int index = i, cnt = 0;
while(!book[index])
{
cnt++;
book[index] = 1;
index = b[index];
}
if(cnt)
cnt2[cnt]++;
}
ll ans = 1;
for(int i = 0; i < tot; i++)
{
ll tmp = 0;
for(int j = 1; j * j <= cnt1[i]; j++)
{
if(cnt1[i]%j == 0)
{
if(j*j == cnt1[i])
tmp += cnt2[j]*j;
else
tmp += cnt2[j]*j + cnt2[cnt1[i]/j]*cnt1[i]/j;
}
}
ans = ans*tmp%Mod;
}
printf("Case #%d: %lld\n",ca++, ans);
}
return 0;
}
#include
#include
#include
#include
using namespace std;
typedef long long ll;
ll n, k;
int main(void)
{
int ca = 1;
while(~scanf("%lld%lld", &n ,&k))
{
printf("Case #%d: ", ca++);
if(k <= n)
{
printf("%lld\n", k);
continue;
}
k -= n;
k %= (2*n-2);
if(k == 0)
{
printf("%lld\n", n);
continue;
}
if(k <= n-1)
printf("%lld\n", k);
else
printf("%lld\n", k%(n-1));
}
return 0;
}
转自:http://blog.csdn.net/qq_28954601/article/details/76177586
sd0061, the legend of Beihang University ACM-ICPC Team, retired last year leaving a group of noobs. Noobs have no idea how to deal with m coming contests. sd0061 has left a set of hints for them.
There are n noobs in the team, the i-th of which has a rating ai. sd0061 prepares one hint for each contest. The hint for the j-th contest is a number bj, which means that the noob with the (bj+1)-th lowest rating is ordained by sd0061 for the j-th contest.
The coach asks constroy to make a list of contestants. constroy looks into these hints and finds out: bi+bj≤bk is satisfied if bi≠bj, bi
There are multiple test cases (about 10).
For each test case:
The first line contains five integers n,m,A,B,C. (1≤n≤10^7,1≤m≤100)
The second line contains m integers, the i-th of which is the number bi of the i-th hint. (0≤bi
For each test case, output “Case #x: y1 y2 ⋯ ym” in one line (without quotes), where x indicates the case number starting from 1 and yi (1≤i≤m) denotes the rating of noob for the i-th contest of corresponding case.
3 3 1 1 1
0 1 2
2 2 2 2 2
1 1
Case #1: 1 1 202755
Case #2: 405510 405510
用题中所给的函数生成 n 个数,然后有 m 次查询,查询数列 a 中第 bi 大的数是多少。
如果单纯想着排序以后直接输出的话会超时,因为 n 最大有 107 ,也就是数列的长度最大也是这些。
那么就应该想想其他线性的解法了, STL 库中实现了 nth_element
函数,其功能是使第 n 大元素处于第 n 个位置,并且比这个元素小的元素都排在它之前,比这个元素大的元素都排在它之后,但不能保证它们是有序的。
时间复杂度:平均为线性。
然后在使用过程中做一点点的优化就可以了,题中有说 bi+bj≤bk ,因此我们在查询时从大往小开始遍历,这样每次都可以减掉数组的一半长度。
#include
#include
#include
#include
#include
using namespace std;
unsigned x, y, z;
unsigned rng61()
{
unsigned t;
x ^= x << 16;
x ^= x >> 5;
x ^= x << 1;
t = x;
x = y;
y = z;
z = t ^ x ^ y;
return z;
}
typedef pair P;
const int manx = 1e7+10;
unsigned a[manx];
unsigned ans[manx];
P b[110];
int main()
{
ios::sync_with_stdio(false);
int n,m,kase=0;
while(cin>>n>>m>>x>>y>>z)
{
for(int i=0; i>b[i].first;
b[i].second=i;
}
for(int i=0; i=0; i--)
{
nth_element(a,a+b[i].first,a+b[i+1].first);
ans[b[i].second]=a[b[i].first];
}
cout<<"Case #"<<++kase<<":";
for(int i=0; i