D牛牛与整除分块
sqrt(n)是分割线。算出来S的个数然后减
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int main()
{
int n,t,x;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&x);
int cnt=(int)sqrt(n)+(int)sqrt(n-(int)sqrt(n));
// cout<<cnt<<'\n';
if(x<=sqrt(n))cout<<x;
else cout<<(int)(cnt-n/x+1);
cout<<'\n';
}
// int n;
// cin>>n;
// for(int i=1;i<=n;i++){
// vector<int>s;
// set<int>st;
// for(int j=1;j<=i;j++){
// s.push_back(i/j);
// st.insert(i/j);
// }
// for(auto x:s){
// cout<<x<<' ';
// }
// cout<<"cnt="<<st.size()<<'\n';
// cout<<'\n';
// }
return 0;
}
G牛牛与比赛颁奖
map+差分
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
map<int,int>mp;
int cot[N];//通过i题的队伍人数
int main()
{
int n,m;
cin>>n>>m;
int l,r;
for(int i=0;i<m;i++){
cin>>l>>r;
mp[l]++;
mp[r+1]--;
}
int linej=0,liney=0,linet=0,j=ceil(1.0*n/10),y=ceil(1.0*n/4),t=ceil(1.0*n/2);
int last=1,cnt=0,maxx=0;
for(auto it:mp){
cot[cnt]+=it.first-last;
last=it.first;
cnt+=it.second;
maxx=max(maxx,cnt);
}
//cout<<j<<' '<<y<<' '<<t<<'\n';
for(int i=maxx;i>=0;i--){
cot[i]+=cot[i+1];
if(cot[i]>=j&&!linej)linej=max(1,i);
if(cot[i]>=y&&!liney)liney=max(1,i);
if(cot[i]>=t&&!linet)linet=max(1,i);
//cout<<cot[i]<<' ';
}
//cout<<'\n';
//cout<<linej<<' '<<liney<<' '<<linet<<'\n';
cout<<cot[linej]<<' '<<cot[liney]-cot[linej]<<' '<<cot[linet]-cot[liney]<<'\n';
return 0;
}
/*
1 1
1 1
1 0 0
*/
H牛牛与棋盘
签到题
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int vis[N][N],col[N][N],n;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
void dfs(int x,int y)
{
for(int i=0;i<4;i++){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx>=0&&xx<n&&yy>=0&&yy<n&&!vis[xx][yy]){
vis[xx][yy]=1;
col[xx][yy]=col[x][y]^1;
dfs(xx,yy);
}
}
}
int main()
{
cin>>n;
col[0][0]=0;
vis[0][0]=1;
dfs(0,0);
// for(int i=0;i<n;i++){
// for(int j=0;j<n;j++){
// if(!vis[i][j]){
// dfs(i,j);
// }
// }
// }
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cout<<col[i][j];
}
cout<<'\n';
}
return 0;
}
I牛牛的“质因数”
这道题用O(nsqrt(n))是过不去的,人家就卡这个,所以普遍做法就是用线性筛筛出1-n的素数,然后分解质因数(分解质因数不能是sqrt(n)),用打表出来的筛可以卡过去。这里的做法是用官方题解给出的筛法树来做的。具体就是线性时间内建树,用fa[x]标记x的父亲,质数的父亲都是1,fa_edge_prime[x]标记x的最小质因子,这样就能在logn下筛出X的所有质因子,然后数字拼接算出答案。总的时间复杂度O(nlogn)。其中还有拼接的复杂度没被算进去,刚好可以卡过去。难点其实就在于建树。官方题解解释的很详细。第一次知道线性筛可以构建筛出质因子的树=~=
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans;
const int N=4e6+5,mod=1e9+7;
int n,prime[N],vis[N],fa[N],fa_edge_prime[N];
void prime_()
{
for(int i=2;i<=n;i++){
if(!vis[i]){
prime[++prime[0]]=i;
fa[i]=1;
fa_edge_prime[i]=i;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++){
vis[i*prime[j]]=1;
fa_edge_prime[i*prime[j]]=prime[j];
fa[i*prime[j]]=i;
if(i%prime[j]==0)break;
}
}
}
ll fun(int x)
{
vector<int>v;//统计质因子 例如26=2,13
while(x!=1){
v.push_back(fa_edge_prime[x]);
x=fa[x];
}
ll res=0,j=1;
for(int i=v.size()-1;i>=0;i--){
ll temp=v[i];
while(temp){//26=213,因此位数>1的需要循环求
ll t=temp%10;
res=(res+t*j%mod)%mod;
j=j*10%mod;
temp/=10;
}
}
return 1ll*res;
}
int main()
{
//freopen("out.txt","w",stdout);
cin>>n;
prime_();
for(int i=2;i<=n;i++){
if(!vis[i])ans=(ans+i)%mod;
else ans=(ans+fun(i))%mod;
}
cout<<ans<<'\n';
return 0;
}
/*
1000000
631719342
100100
835426760
10000
297701107
*/
方法2:埃氏筛+dp
f[x]=f[x/pi]*10^(len(pi))+pi(pi是x的最大质因子)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e6+5,mod=1e9+7;
ll f[N],n;
ll cal(ll x)
{
ll t=10;
for(int i=1;i<=x;i++)
t=t*10%mod;
return t;
}
void prime_()
{
for(int i=2;i<=n;i++){
if(!f[i]){
f[i]=i;
for(int j=2*i;j<=n;j+=i)
f[j]=(f[j/i]*cal(log10(i))%mod+i)%mod;
}
}
}
int main()
{
cin>>n;
prime_();
ll ans=0;
for(int i=2;i<=n;i++)
ans=(ans+f[i])%mod;
cout<<ans<<'\n';
return 0;
}
J牛牛想要成为hacker
前一段填充斐波那契数列,后边填充比前边小的即可。因此把菲波那切数列中前2个挪到后面即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5;
ll f[N];
int main()
{
int n;
cin>>n;
f[1]=2;f[2]=3;
for(int i=3;i<=42;i++){
f[i]=f[i-1]+f[i-2];
}
int cnt=0;
for(cnt=1;cnt<=min(n,42);cnt++){
cout<<f[cnt]<<' ';
}
for(int i=cnt;i<=n;i++){
cout<<1<<' ';
}
cout<<'\n';
return 0;
}
//46