题目大意:有一个数列{xi},每次给出一个询问[l, r],即问 S(l ,r)是l和r之间的素数,f(p)表示数列{xi}中整除p的个数
思路:筛法,显然xi的顺序是无所谓的,我们把它记录下来,然后做筛法,如果一个素数筛合数的过程中遇到一个数的话显然得记到这个素数的头上,然后再把这样得到的表求一个sum就行
#include<iostream>
#include<cstdio>
#define maxn 10000009
int sum[maxn*],ans[maxn*];
bool visit[maxn*];
int main()
{
int n,m,x,y;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&x);
sum[x]++;
}
for(int i=;i<=maxn;i++)
{
if(!visit[i])
{
for(int j=;j*i<=maxn;j++)
{
visit[i*j]=;
ans[i]+=sum[i*j];
}
}
ans[i]+=ans[i-];
}
scanf("%d",&m);
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
if(x>=maxn )x=maxn;
if(y>maxn)y=maxn;
printf("%d\n",ans[y]-ans[x-]);
} return ;
}
cf 14 E Camels
题目大意:问你长度为n的数列,其中只有1 到4 ,有t个峰 t-1个谷并且不存在连续两个相同高度的序列的个数
思路:dp[i][j][k][b]表示现在到第i个数字,第i个数字为j,有k个驼峰,如果第i个点高于第i-1个点那么b=0,不然b=1,可以很自然的推出转移,不过需要注意的是仔细画一下就可以发现峰和谷必然是交替出现的,并且在头和尾上必然是一个上升一个下降的,不然不可能满足t-1个谷,所以在i=2的时候强制上升就可以了
#include<iostream>
#include<cstdio>
using namespace std;
int dp[][][][];
int main()
{
int n,t;
scanf("%d%d",&n,&t);
for(int i=;i<=;i++)dp[][i][][]=;
for(int i=;i<=n;i++)
{
for(int j=;j<=;j++)
{
for(int k=;k<=min(i,t);k++)
{
for(int m=;m<=j-;m++)
{
dp[i][j][k][]+=dp[i-][m][k][]+dp[i-][m][k][];
}
if(i!=)for(int m=j+;m<=;m++)
{
dp[i][j][k][]+=dp[i-][m][k-][]+dp[i-][m][k][];
}
}
}
}
int ans=;
for(int i=;i<=;i++)ans+=dp[n][i][t][];
printf("%d\n",ans);
return ;
}
cf 69D Dot
题目大意:一开始在坐标系中有一个点,两人轮流操作,每次操作可以将一个点走一个偏移量(偏移量是给定的,题目给出了一坨偏移量,每次选择一个),或者每个选手有一次机会把点做y=x的对称操作,谁让点离远点欧几里的距离超过d谁就输,问谁胜
思路:博弈dp,利用一个P有一个子局面是N态,而N态所有子局面都是P态的思路进行记忆话搜索,值得注意的是y=x对称的这个操作是没有用的,显然这个操作不会改变和原点的距离,并且如果对手这个操作以后改变了当前局面的N P状态的话也可以改回来,由于只能改一次,对于胜负状态没有影响
#include<cstdio>
#include<iostream>
#define maxn 1000
using namespace std;
int x[maxn],y[maxn],d,n,xx,yy,dp[][];
int dfs(int a,int b)
{
if(a*a+b*b>d*d)return ;
int &u=dp[a+][b+];
if(u!=)return u;
for(int i=;i<=n;i++)if(dfs(a+x[i],b+y[i])==)return u=;
return u=;
}
int main()
{
scanf("%d%d%d%d",&xx,&yy,&n,&d);
for(int i=;i<=n;i++)scanf("%d%d",&x[i],&y[i]);
if(dfs(xx,yy)==)puts("Anton");else puts("Dasha");
return ;
}
CF 276 D. Little Girl and Maximum XOR
题目大意:在区间[L,R]中最大的a^b的值
思路:当时做群赛的时候做的这题,xiaoxin机智的打表得出了答案都是2^n-1的形式,然后只要知道n是多少就行,然后仔细想想就能发现其实就是L和R中从高位算起第一位二进制不同的位
#include<iostream>
#include<cstdio>
#include<cstring>
#define LLD "%lld"
using namespace std;
int main()
{
long long a,b;
scanf(LLD LLD,&a,&b);
long long cnt=,n=a^b;
while(n>)
{
cnt++;
n>>=;
}
printf(LLD"\n",(1LL<<(cnt))-);
return ;
}
CF 257 B. Playing Cubes
题目大意:有N个蓝木块和M个红木块,两人分别在其中拿出一个放成一排,一人是以最后相邻同色木块数量得分,一人是以相邻不同色木块计分,两人都用最优策略使自己得分最高问最后得分情况
思路:稍微想想就知道最后序列是这样的BRRBBRRBBRRRRRRRRRRR总是以少的那个颜色开头,然后对着这串多看两眼就能想到答案了
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int a,b;
scanf("%d%d",&a,&b);
if(a<b)swap(a,b);
printf("%d %d\n",a-,b);
return ;
}
CF 343 B. Alternating Current
题目大意:给你两根绳子,弯弯绕,问你最后能不能仅扯着四个线头把两条绳子分开
思路:显然++或者--这种情况直接可以舍掉的,然后很自然的想到用栈来搞,然后就没有然后了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#define maxn 500000
using namespace std;
stack<int>q;
char ch[maxn];
int main()
{
scanf("%s",ch+);
int len=strlen(ch+);
for(int i=;i<=len;i++)
{
char c=ch[i];
if(!q.empty())
{
char u=q.top();
if(u==c)q.pop();else q.push(c);
}
else q.push(c);
}
if(q.empty())puts("Yes");else puts("No");
return ;
}