您的位置:首页 > 其它

51nod一级算法题全部题解

2017-05-10 15:47 183 查看

  51nod一级算法题

1001数组中和等于k的数对:对数组排序,枚举其中一个数,然后二分对应的另一个数。

1002数塔取数问题:初等的动态规划,自底向上进行更新就好。

1003阶乘后面0的数量:分析可以发现,只需要统计5,5^2,5^3...的倍数在n中出现的次数,最后相加就是结果。
#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 5*1e4+5;
const int mod = 1e9+7;
const int Hash = 10000;
const int INF = 1<<30;

int n;
int arr[Max];
int main( )
{
//freopen("input.txt", "r", stdin);
while(~scanf("%d", &n))
{
int ans = 0;
ll k = 5;
while(n/k)
{
ans += n/k;
k *= 5;
}
cout<<ans<<endl;
}
return 0;
}


1004n^n的末位数字:末位数字只和末位数字有关,简单的快速幂即可解,logn的复杂度。
#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 5*1e4+5;
const int mod = 1e9+7;
const int Hash = 10000;
const int INF = 1<<30;

int n;
int arr[Max];
int main( )
{
//freopen("input.txt", "r", stdin);
while(~scanf("%d", &n))
{
int k = n%10;
int ans = k, t = 1;
while(n>1)
{
if(n%2)
t = (t*ans)%10;
ans = (ans*ans)%10;
n /= 2;
}
ans = (ans*t)%10;
cout<<ans<<endl;
}
return 0;
}


1009数字1的数量:将数拆分为位,统计每一位出现1的数量,最后加和。当该位为1时,该位出现的数字1数量等于该位高位数字组成的数乘以本位的权重再加上低位数字组成的数加一; 当该位不为1时候,为0的话,等于高位数乘以本位权重,大于一的话等于高位数加一乘以本位权重。
#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 1e6+5;
const int mod = 1e9+7;
const int Hash = 10000;
const int INF = 1<<30;

int n;
int main( )
{
//freopen("input.txt", "r", stdin);
while(~scanf("%d", &n))
{
int ans= 0;
int i=1, current=0, before = 0, after = 0;
while(n/i != 0)
{
current = (n/i)%10;
before = n/(10*i);
after = n%i;
if(current == 0)
ans += before*i;
else if(current == 1)
ans += before*i+after+1;
else
ans += (before+1)*i;
i *= 10;
}
cout<<ans<<endl;
}
return 0;
}


1015水仙花数:由于输入数据的范围,可以取巧只算出1000以内的水仙花数和1000以外的一个水仙花数,然后对于每次询问查询即可。

1080两个数的平方和:枚举到sqrt(n)即可

1082与7无关的数:用数组预先计算好n以内的所有结果,然后查询,不会超时。
#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 1e6+5;
const int mod = 1e9+7;
const int Hash = 10000;
const int INF = 1<<30;

int ans;
int T, n, m;
ll arr[Max];
bool relate7(int a)
{
int k = 1e6;
while(a/k==0)
k /= 10;
for(; k>0; k/=10)
{
int t = a/k;
if(t == 7)
return true;
a -= t*k;
}
return false;
}
int main( )
{
//freopen("input.txt", "r", stdin);
for(ll i=1; i<Max; i++)
{
if(i%7 && !relate7(i))
arr[i] = arr[i-1]+i*i;
else
arr[i] = arr[i-1];
}
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
printf("%lld\n", arr
);
}
return 0;
}


1083矩阵取数问题:基础动态规划

1087 1 10 100 1000:发现1总是位于n(n+1)/2,二分求解输入是否可能为该式的计算结果,其中n只能取整数,可以就是1,不可以就是0。
#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 1000;
const int mod = 1e9+7;
const int Hash = 10000;
const int INF = 1<<30;

ll n, m, T;
ll f(ll n)
{
return (n+1)*n/2;
}
int main( )
{
//freopen("input.txt", "r", stdin);
scanf("%lld", &T);
while(T--)
{
scanf("%lld", &n);
if(n==1 || n==2)
{
cout<<1<<endl;
continue;
}
n--;
ll low=1, high = 1e9, flag = 0;
while(low <= high)
{
ll mid = (low+high)>>1;
if(f(mid) == n)
{
flag = 1;
break;
}
else if(f(mid)>n)
high = mid-1;
else
low = mid+1;
}
if(flag)
cout<<1<<endl;
else
cout<<0<<endl;
}
return 0;
}


1090 3个数和为0:枚举其中两个,二分最后一个。

1091线段的重叠:贪心,优先选取左端点小的。
#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 5*1e4+5;
const int mod = 1e9+7;
const int Hash = 10000;
const int INF = 1<<30;
int T,n,m;

bool cmp(const pair<int ,int>& a, const pair<int,int>& b)
{
if(a.first != b.first)
return a.first<b.first;
return a.second<b.second;
}
int main( )
{
//freopen("input.txt", "r", stdin);
pair<int, int> line[Max];
while(~scanf("%d", &n))
{
int a, b;
for(int i=0; i<n; i++)
{
scanf("%d%d", &a, &b);
line[i].first = min(a, b);
line[i].second = max(a, b);
}
sort(line, line+n, cmp);
int ans = 0;
int temp = line[0].second;
for(int i=1; i<n; i++)
{
if(line[i].first>=temp)
temp = line[i].second;
else if(line[i].second > temp)
{
ans = max(ans, temp-line[i].first);
temp = line[i].second;
}
else
ans = max(line[i].second-line[i].first, ans);
}
cout<<ans<<endl;
}
return 0;
}


1182完美字符串: 基础的贪心

1283最小周长:数学知识,基本不等式。

1284 2 3 5 7的倍数:包含排斥原理。
#include<iostream>
#include<cstring>
#include<math.h&
4000
gt;
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 1e6+5;
const int mod = 1e9+7;
const int Hash = 10000;
const int INF = 1<<30;
int T,n,m;

ll  f(ll n)
{
ll a = n/2 + n/3 + n/5 + n/7;
ll b = n/6 + n/10 + n/14 + n/15 + n/21 + n/35;
ll c = n/30 + n/42 + n/70 + n/105;
ll d = n/210;
return n-a+b-c+d;
}
int main( )
{
//freopen("input.txt", "r", stdin);
ll n;
while(~scanf("%lld", &n))
{
ll ans = f(n);
cout<<ans<<endl;
}
return 0;
}


1289大鱼吃小鱼:很有意思的模拟,详见代码。
#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int Max = 1e6+5;
const int mod = 1e9+7;
const int Hash = 10000;
const int INF = 1<<30;
int T,n,m;

int main( )
{
//freopen("input.txt", "r", stdin);
while(~scanf("%d", &n))
{
ll ans = 0;
int heavy[Max], dir[Max];
for(int i=0; i<n; i++)
scanf("%lld%lld", heavy+i, dir+i);
int big = 0;
for(int i=0; i<n; i++)
{
if(dir[i]==0 && heavy[i]>big)
{
ans++;
big = 0;
}

else if(dir[i]==1)
big = max(big, heavy[i]);
}
big = 0;
for(int i=n-1; i>=0; i--)
{
if(dir[i]==1 && heavy[i]>big)
{
ans++;
big = 0;
}

else if(dir[i]==0)
big = max(big, heavy[i]);
}
cout<<ans<<endl;
}
return 0;
}


1305Pairwise Sum and Divide:模拟水题。

1344走格子:模拟水题。

1347旋转字符串:分析一下,符合的一定是偶数长度,并且前半段和后半段相等的串。

1381硬币游戏:数学问题,每两条直线的间距都是1,所以期望显然就是圆的直径长度除以1,就是2R
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  51nod