zoukankan      html  css  js  c++  java
  • 辣些数论的思维题(枯了)

    BZOJ 2659 算不出的算式

    • 关键是要想到这两个式子的几何意义。
    • 然后如图,以p1=5,p2=3为例子,整个矩形一定是被均分了的。
    • 如上图,单看每一列,绿点把红点分为上下两部分,绿点的位置又是中心对称的,所以整个红点(除了在对角线上的)都被等分到上三角和下三角了。
    • 由于p,q都是质数所以对角线上是不会有整点哒
    • 当p,q相等时,式子变成[1/p] + [2/p] + ... + [ ((p-1)/2) /p ]
    • 由 [ (x+n*p) / p ] =n   (x<p)  可知上面的是个有规律的数列。
    • 代码:
    •  1 #include <bits/stdc++.h>
       2  
       3 using namespace std;
       4 typedef unsigned long long ull;
       5  
       6 int main(){
       7     ull p,q,ans;
       8     cin>>p>>q;
       9     if(p==q) {
      10         ull k=(q-1)/2;  //1+...+k
      11         ans=(1+k)*k/2;
      12         cout<<ans*2<<endl;
      13         return 0;
      14     }
      15     ans=(p+1)*(q+1)/4;
      16     ans-=((p+1)/2+(q+1)/2);
      17     cout<<ans+1<<endl;
      18     return 0;
      19 }
      20
      quq

    洛谷P3951 NOIP2017 小凯的疑惑

    • 倒回去看那年的题,所以为什么会爆0,三十分都没有啊(╯‵□′)╯︵┻━┻
    • 拿三和五为例子,考虑数轴
    • 这些是三的倍数能指着的点,可以看出所有的数里每三个数就有一个能被表示。
    • 现在看加上5的情况
    • 这里由于第一个5在三的后面两位,一直倍数下去,这样所有的数每三个数就有两个能被表示
    • 而第二个5,就是10正好踩到后面一位,这样这之后的每三个数的这一位一定能被表示
    • 这样就能表示完那后面所有的数了。
    • 所以任意两个p,q(互质)的情况是一样的,不妨假设p<q
    • q%p
    • 2*q%p
    • 3*q%p
    • ......
    • (p-1)*q%p
    • 可以知道上面这些的结果一定都不一样,(如果一样,那就一定有p是q的因数,这与他俩互质矛盾)
    • 所以在p*q之前q之间的空挡一定被q踩完,这之后的任意数都能被表示
    • 那第一个不能被表示的数呢?
    • 我们知道最后一个被踩的空挡是(p*q)-q,在这个空档之前的这个空挡都是踩不到的,所以就在它前一个就是最大的无法表示的数了,即为p*q-p-q
    • 代码:
       1 #include <bits/stdc++.h>
       2 
       3 using namespace std;
       4 typedef long long ll;
       5 
       6 int main(){
       7     ll a,b; //a>b
       8     cin>>a>>b;
       9     cout<<(a*b)-a-b<<endl;
      10     return 0;
      11 }
      嘤击长空

    BZOJ1008: [HNOI2008]越狱

    • 考虑不发生越狱的情况,m* ( m-1 )^(n-1)
    • 全部情况:m^n
    • 快速幂
    • 代码:
       1 #include <bits/stdc++.h>
       2 #define mod 100003
       3  
       4 using namespace std;
       5 typedef long long ll;
       6 ll m,n;
       7  
       8 ll exp(ll x,ll v){
       9     if(x==1) return v;
      10     ll t=exp(x/2,v);
      11     t=(t*t)%mod;
      12     return (x%2) ? (t*v)%mod : t;
      13 }
      14  
      15 int main(){
      16     cin>>m>>n;
      17     ll a=exp(n,m),b=exp(n-1,m-1);
      18     ll ans=a-(m*b)%mod;
      19     if(ans<0) ans+=mod;
      20     cout<<ans<<endl;
      21     return 0;
      22 }
      嘤帝质疑

    BZOJ2818: Gcd

    • 题意:给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
      数对(x,y)有多少对.    其中1<=N<=10^7
    • 欧拉函数
    • 先枚举gcd(x,y)的值,然后再求所有这些数中有枚举的这个数的因子的数中互质的对数,后者用欧拉函数再求一个前缀和就ok了
    • 代码(注意欧拉函数求前缀和到后面会爆int,要开long long才行)
       1 #include <bits/stdc++.h>
       2  
       3 using namespace std;
       4 typedef long long ll;
       5 ll phi[10000005];
       6 int pri[10000005],table[10000005]={0};
       7 int cp=-1,n;
       8 ll ans=0;
       9  
      10 void getphi(){
      11     for (int i=2; i<=1e7; i++) {
      12         if(!table[i]) { pri[++cp]=i; phi[i]=i-1; }
      13         for (int j=0; j<=cp; j++){
      14             ll t=pri[j]*i;
      15             if(t>1e7) break;
      16             table[t]=1;
      17             if(i%pri[j]==0) { phi[t]=phi[i]*pri[j]; break;}
      18             phi[t]=phi[i]*(pri[j]-1);
      19         }
      20     }
      21 }
      22  
      23 int main(){
      24     getphi();
      25     for (int i=1; i<=1e7; i++) phi[i]+=phi[i-1];
      26     cin>>n;
      27     for (int i=0; i<=cp; i++) {
      28         if(n<pri[i]) break;
      29         ans+= (phi[ n/pri[i] ]<<1) ;
      30         ans++;
      31     }
      32     cout<<ans<<endl;
      33     return 0;
      34 }
      嘤雄不朽

    BZOJ2705: [SDOI2012]Longge的问题

    • 题意: 给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)   其中0<N<=2^32。

    • 这个题没做出来主要是因为没考虑过枚举N的因数(其实是因为我人傻)
    • 对啊根号N就可以枚举N的所有因数了何必想的辣么复杂呢
    • 代码:
       1 #include <bits/stdc++.h>
       2  
       3 using namespace std;
       4 typedef long long ll;
       5  
       6 ll phi(ll x){
       7     ll sqx=sqrt(x),tx=x;
       8     for (ll i=2; i<=sqx; i++) {
       9         if(tx%i) continue;
      10         x/=i;
      11         x*=(i-1);
      12         while(tx%i==0) tx/=i;
      13         if(tx==1) break;
      14     }
      15     if(tx>1) { x/=tx; x*=(tx-1); }
      16     return x;
      17 }
      18  
      19 int main(){
      20     ll ans=0,n;
      21     cin>>n;
      22     ll m=sqrt(n);
      23     for (int i=2; i<=m; i++) {
      24         if(n%i) continue;
      25         ans+=phi(n/i)*i;
      26         if(i*i<n) ans+=(n/i)*phi(i);
      27     }
      28     ans+=(n+phi(n));
      29     cout<<ans<<endl;
      30     return 0;
      31 }
      满门嘤烈

     

    BZOJ1045: [HAOI2008] 糖果传递

    • 有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
    • 假设第x(i)个人给了第x(i+1)个人b个糖果,然后如果一个人接到的糖果是n+b的话,算一下最后每个人的糖果数就可以知道它拿出去的也是一个整数加b的形式,那最后要求的ans=min对abs(n+b)求和;b是唯一的变量,n是可以算出来的整数
    • 于是就转化成了一种常见模型:求数轴上n个点到哪一点距离之和最短。。。
    • 代码:
       1 #include <cstdio>
       2 #include <iostream>
       3 #include <algorithm>
       4 #define nmax 1000010
       5  
       6 using namespace std;
       7 typedef long long ll;
       8 int c[nmax],b[nmax]={0};
       9 ll tot=0,a=0;
      10 int n;
      11  
      12 ll cntdis(ll x){
      13     ll d=0;
      14     for (int i=0; i<n; i++) d+=abs(b[i]-x);
      15     return d;
      16 }
      17  
      18 int main(){
      19     cin>>n;
      20     for (int i=0; i<n; i++) {
      21         scanf("%d",&c[i]);
      22         tot+=c[i];
      23     }
      24     a=tot/n;
      25     for (int i=1; i<n; i++) b[i]=b[i-1]-a+c[i];
      26     for (int i=1; i<n; i++) b[i]*=(-1);
      27     sort(b,b+n);
      28     if(n&1) cout<<cntdis(b[n/2])<<endl;
      29     else cout<<cntdis(b[n/2-1])<<endl;
      30     return 0;
      31 }
      嘤姿勃发
  • 相关阅读:
    Java-16 常用包装类
    Java-15 String类
    flask实现web端微信登录
    Flask-excel导出数据
    Java-14 单例模式
    Java-13 接口
    Java-12 抽象类
    结对项目:一个自动生成小学四则运算题目的命令行程序(c++)
    软工作业:第一次个人项目作业
    操作系统笔记一:操作系统引论
  • 原文地址:https://www.cnblogs.com/jiecaoer/p/11342238.html
Copyright © 2011-2022 走看看