目录
P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
视频链接 : 秒懂算法三
1147 连续自然数和
原题链接 :
思路1 : (按照EK的讲解,hh)
- 题意 : 在1-m的序列中找连续的一段序列[l,r],要求满足sum([l,r]) = m;
- 那么就容易想到等差数列的求和公式,sum = (l+r)*(r-l+1)/2;
- 对于题目也就是 : (l+r) * (r-l+1) = 2*m;
- 那么也就是找2*m的两个因子 (x1,x2) : x1 = (l+r),x2 = (r-l+1);
- 对于上面的式子有 : r = (x1+x2-1)/2,l =x1=r;
- 最后满足 0<=l && l<=r && (l+r)*(r-l+1) == 2*m之后,就可以将l,r添加到答案ans中
- 对ans进行排序之后,最后输出ans即可
求因子算法模板 :
对于这种思路,一个重要的点是求2*m的所有因子,下面贴上求x的所有因子的代码 :
vector<int> get_divisors(int x){
vector<int> res;
for (int i = 1; i <= x / i; i ++ )
if (x % i == 0){
res.push_back(i);
if (i != x / i) res.push_back(x / i);
}
sort(res.begin(),res.end());
return res;
}
代码 1 (数学):
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef long long LL;
int gcd(int a,int b){ return b==0 ? a : gcd(b,a%b); }
int lcm(int a,int b){ if(a==0||b==0) return 0; return (a*b)/gcd(a,b); }
bool is_prime(int x){if(x<2) return false;
for(int i=2;i<=x/i;i++) if(x%i==0) return false; return true;}
vector<int> get_divisors(int x){
vector<int> res;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0){
res.push_back(i);
if (i != x / i) res.push_back(x / i);
}
sort(res.begin(),res.end());
return res;
}
const int N = 2e5+10;
int m;
inline void solve(){
cin>>m;
vector<int> div;
div = get_divisors(2*m);
int l , r;
// sum([l,r]) == m -> (l+r)*(r-l+1) = 2*m;
// 2*m的两个因子 :
// x1 : (l+r) x2 : (r-l+1)
// 则 : l = x1 - r r = (x1 + x2 - 1)/2;
vector<pair<int,int>> ans;
for(auto& x1 : div){
for(auto& x2 : div){
if( (x1 +x2-1) % 2 ) continue;
int r = (x1 + x2 -1)/2;
int l = x1 - r;
if(0<=l && l<=r && (l+r)*(r-l+1) == 2*m ){
ans.push_back({l,r});
}
}
}
sort(ans.begin(),ans.end());
for(const auto &pair : ans){
cout << pair.first << " " << pair.second <<endl;
}
return ;
}
int main()
{
IOS
int _;
// cin >> _;
_ = 1;
while(_ --) solve();
return 0;
}
思路 2(暴力) :
数据不算大,直接暴力即可,一遍遍历,1e3左右
代码2(暴力) :
#include<bits/stdc++.h>
using namespace std;
int m,sum;
int main(){
cin>>m;
for(int i=1;i<=m/2;i++){
sum = i;
for(int j=i+1;j<m;j++){
sum += j;
if(sum==m) cout << i << " " <<j<<endl;
else if(sum>m){ break; }
}
}
}
P1125 [NOIP2008 提高组] 笨小猴
原题链接 :
思路 :
- 哈希表 : 用size = 26的数组z来模拟哈希表,存字符串s中出现各字母的次数
- 判断质数 : 本题重要的一点是如何判断质数,下面将附上试除法判断质数的算法模板;
试除法判断质数算法模板 :
bool is_prime(int x) //判定质数
{
if(x<2) return false;
for(int i=2;i<=x/i;i++)
if(x%i==0)
return false;
return true;
}
代码 :
#include<bits/stdc++.h>
using namespace std;
bool is_prime(int x) //判定质数
{
if(x<2) return false;
for(int i=2;i<=x/i;i++)
if(x%i==0)
return false;
return true;
}
int main()
{
string s;
cin>>s;
int n=s.size();
int z[26]={0};
for(int i=0;i<n;i++) z[int(s[i]-'a')]++;
int maxn=-1,minn=101;
for(int i=0;i<26;i++)
if(z[i]>maxn)
maxn=z[i];
else if(z[i]<minn&&z[i]!=0)
minn=z[i];
int k=maxn-minn;
if(is_prime(k))
{
cout<<"Lucky Word"<<endl;
cout<<(maxn-minn);
}
else
{
cout<<"No Answer"<<endl;
cout<<0;
}
return 0;
}
P1605 迷宫
原题链接 :
思路 :
一道dfs模板题,注意细节即可,思路在代码里!!!
代码 :
#include<bits/stdc++.h>
using namespace std;
const int N = 100;
int sx,sy,fx,fy,n,m,t,sum;
int a[N][N];
void dfs(int x,int y){
if(x==fx && y==fy){ sum++ ; return ; }//到达终点
if(a[x][y]==0||a[x][y]==2) return ;//遇到障碍或走过
a[x][y] = 2;//标记走过
dfs(x+1,y);//右
dfs(x-1,y);//左
dfs(x,y+1);//下
dfs(x,y-1);//上
a[x][y]=1;//还原现场
}
int main()
{
cin>>n>>m>>t;
cin>>sx>>sy>>fx>>fy;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j] = 1;//可以走
for(int i=1;i<=t;i++){
int x,y;cin>>x>>y;
a[x][y] = 0;//0表示障碍物
}
if(a[fx][fy]==0){//终点是障碍物
cout<<0<<endl;
return 0;
}
dfs(sx,sy);//dfs
cout<<sum<<endl;
return 0;
}
P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G
原题链接 :
[NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷s
思路 :
使用优先队列,每次优先合并较小的两堆果子。
代码 :
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e4+10;
LL ans,n,x,a,b;
int main()
{
cin>>n;
priority_queue<int,vector<int>,greater<int>> pq;
for(int i=1;i<=n;i++){
cin>>x;
pq.push(x);
}
while(pq.size()>1){
a = pq.top();pq.pop();
b = pq.top();pq.pop();
ans += a+b;
pq.push(a+b);
}
cout<<ans<<endl;
return 0;
}
P1037 [NOIP2002 普及组] 产生数
原题链接 :
https://www.luogu.com.cn/problem/P1037
思路 :
图 + dfs;
代码 :
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 15;
string s;
int k;
vector<int> g[N];
int cnt[N];
bitset<N> vis;
void dfs(int x){
vis[x] = true;
for(const auto &y : g[x]){
if(!vis[y]) dfs(y);
}
}
void output(__int128 x){
if(x/10) output(x/10);
putchar(x%10+'0');
}
int main()
{
cin>>s>>k;
for(int i=1;i<=k;i++){
int x,y;cin>>x>>y;
g[x].push_back(y);
}
for(int i=0;i<=9;i++){
vis.reset();
dfs(i);
cnt[i] = vis.count();
}
__int128 ans = 1;
for(const auto &i : s){
ans *= cnt[i-'0'];
}
output(ans);
return 0;
}
欢迎交流和指出问题!!!